diff --git a/Safari Shared/Models/Requests/EthereumSafariRequest.swift b/Safari Shared/Models/Requests/EthereumSafariRequest.swift index 993259ee..f472bb6a 100644 --- a/Safari Shared/Models/Requests/EthereumSafariRequest.swift +++ b/Safari Shared/Models/Requests/EthereumSafariRequest.swift @@ -21,8 +21,8 @@ extension SafariRequest { let method: Method let address: String - let chain: EthereumNetwork? - let switchToChain: EthereumNetwork? + let currentChainId: Int? + let switchToChainId: Int? let parameters: [String: Any]? init?(name: String, json: [String: Any]) { @@ -32,21 +32,19 @@ extension SafariRequest { self.address = address self.method = method - if let network = json["networkId"] as? String, let networkId = Int(network) { - self.chain = EthereumNetwork(rawValue: networkId) + if let currentChainId = json["chainId"] as? String, let chainId = Int(hexString: currentChainId) { + self.currentChainId = chainId } else { - self.chain = nil + self.currentChainId = nil } let parameters = json["object"] as? [String: Any] self.parameters = parameters - if let chainId = parameters?["chainId"] as? String, - let networkId = Int(hexString: chainId), - let chain = EthereumNetwork(rawValue: networkId) { - self.switchToChain = chain + if let toChainId = parameters?["chainId"] as? String, let chainId = Int(hexString: toChainId) { + self.switchToChainId = chainId } else { - self.switchToChain = nil + self.switchToChainId = nil } } diff --git a/Safari Shared/Models/Requests/UnknownSafariRequest.swift b/Safari Shared/Models/Requests/UnknownSafariRequest.swift index cb6ba6b3..0a965070 100644 --- a/Safari Shared/Models/Requests/UnknownSafariRequest.swift +++ b/Safari Shared/Models/Requests/UnknownSafariRequest.swift @@ -14,7 +14,7 @@ extension SafariRequest { struct ProviderConfiguration { let provider: InpageProvider let address: String - let network: EthereumNetwork? + let chainId: String? } let method: Method @@ -37,7 +37,7 @@ extension SafariRequest { case .ethereum: guard let response = try? jsonDecoder.decode(ResponseToExtension.Ethereum.self, from: data), let address = response.results?.first else { continue } - configurations.append(ProviderConfiguration(provider: provider, address: address, network: EthereumNetwork.withChainId(response.chainId))) + configurations.append(ProviderConfiguration(provider: provider, address: address, chainId: response.chainId)) case .unknown, .multiple: continue } diff --git a/Safari Shared/Resources/inpage.js b/Safari Shared/Resources/inpage.js index 639e23fa..7c9a9b6e 100644 --- a/Safari Shared/Resources/inpage.js +++ b/Safari Shared/Resources/inpage.js @@ -1 +1 @@ -(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i=o.length)return{done:true};return{done:false,value:o[i++]}},e:function e(_e){throw _e},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var normalCompletion=true,didErr=false,err;return{s:function s(){it=it.call(o)},n:function n(){var step=it.next();normalCompletion=step.done;return step},e:function e(_e2){didErr=true;err=_e2},f:function f(){try{if(!normalCompletion&&it["return"]!=null)it["return"]()}finally{if(didErr)throw err}}}}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i1&&arguments[1]!==undefined?arguments[1]:true;this.idMapping.tryFixId(payload);return new Promise(function(resolve,reject){if(!payload.id){payload.id=_utils["default"].genId()}_this2.callbacks.set(payload.id,function(error,data){setTimeout(function(){if(error){reject(error)}else{resolve(data)}},1)});_this2.wrapResults.set(payload.id,wrapResult);switch(payload.method){case"eth_accounts":case"eth_coinbase":case"net_version":case"eth_chainId":case"eth_sign":case"personal_sign":case"personal_ecRecover":case"eth_signTypedData_v3":case"eth_signTypedData":case"eth_signTypedData_v4":case"eth_sendTransaction":case"eth_requestAccounts":case"wallet_addEthereumChain":case"wallet_switchEthereumChain":case"wallet_requestPermissions":case"wallet_getPermissions":return _this2._processPayload(payload);case"eth_newFilter":case"eth_newBlockFilter":case"eth_newPendingTransactionFilter":case"eth_uninstallFilter":case"eth_subscribe":throw new _error["default"](4200,"Tokenary does not support calling ".concat(payload.method,". Please use your own solution"));default:_this2.callbacks["delete"](payload.id);_this2.wrapResults["delete"](payload.id);return _this2.rpc.call(payload).then(function(response){wrapResult?resolve(response):resolve(response.result)})["catch"](reject)}})}},{key:"_processPayload",value:function _processPayload(payload){if(!this.didGetLatestConfiguration){this.pendingPayloads.push(payload);return}switch(payload.method){case"eth_accounts":return this.sendResponse(payload.id,this.eth_accounts());case"eth_coinbase":return this.sendResponse(payload.id,this.eth_coinbase());case"net_version":return this.sendResponse(payload.id,this.net_version());case"eth_chainId":return this.sendResponse(payload.id,this.eth_chainId());case"eth_sign":return this.eth_sign(payload);case"personal_sign":return this.personal_sign(payload);case"personal_ecRecover":return this.personal_ecRecover(payload);case"eth_signTypedData_v3":return this.eth_signTypedData(payload,false);case"eth_signTypedData":case"eth_signTypedData_v4":return this.eth_signTypedData(payload,true);case"eth_sendTransaction":return this.eth_sendTransaction(payload);case"eth_requestAccounts":if(!this.address){return this.eth_requestAccounts(payload)}else{return this.sendResponse(payload.id,this.eth_accounts())}case"wallet_addEthereumChain":return this.wallet_addEthereumChain(payload);case"wallet_switchEthereumChain":return this.wallet_switchEthereumChain(payload);case"wallet_requestPermissions":case"wallet_getPermissions":var permissions=[{parentCapability:"eth_accounts"}];return this.sendResponse(payload.id,permissions)}}},{key:"emitConnect",value:function emitConnect(chainId){this.emit("connect",{chainId:chainId})}},{key:"eth_accounts",value:function eth_accounts(){return this.address?[this.address]:[]}},{key:"eth_coinbase",value:function eth_coinbase(){return this.address}},{key:"net_version",value:function net_version(){return parseInt(this.chainId,16).toString(10)||null}},{key:"eth_chainId",value:function eth_chainId(){return this.chainId}},{key:"eth_sign",value:function eth_sign(payload){var buffer=_utils["default"].messageToBuffer(payload.params[1]);var hex=_utils["default"].bufferToHex(buffer);if((0,_isutf["default"])(buffer)){this.postMessage("signPersonalMessage",payload.id,{data:hex})}else{this.postMessage("signMessage",payload.id,{data:hex})}}},{key:"personal_sign",value:function personal_sign(payload){var message=payload.params[0];var buffer=_utils["default"].messageToBuffer(message);if(buffer.length===0){var hex=_utils["default"].bufferToHex(message);this.postMessage("signPersonalMessage",payload.id,{data:hex})}else{this.postMessage("signPersonalMessage",payload.id,{data:message})}}},{key:"personal_ecRecover",value:function personal_ecRecover(payload){this.postMessage("ecRecover",payload.id,{signature:payload.params[1],message:payload.params[0]})}},{key:"eth_signTypedData",value:function eth_signTypedData(payload,useV4){this.postMessage("signTypedMessage",payload.id,{raw:payload.params[1]})}},{key:"eth_sendTransaction",value:function eth_sendTransaction(payload){this.postMessage("signTransaction",payload.id,payload.params[0])}},{key:"eth_requestAccounts",value:function eth_requestAccounts(payload){this.postMessage("requestAccounts",payload.id,{})}},{key:"wallet_watchAsset",value:function wallet_watchAsset(payload){var options=payload.params.options;this.postMessage("watchAsset",payload.id,{type:payload.type,contract:options.address,symbol:options.symbol,decimals:options.decimals||0})}},{key:"wallet_switchEthereumChain",value:function wallet_switchEthereumChain(payload){if(this.chainId!=payload.params[0].chainId){this.postMessage("switchEthereumChain",payload.id,payload.params[0])}else{this.sendResponse(payload.id,[this.address])}}},{key:"wallet_addEthereumChain",value:function wallet_addEthereumChain(payload){this.postMessage("addEthereumChain",payload.id,payload.params[0])}},{key:"processTokenaryResponse",value:function processTokenaryResponse(id,response){if(response.name=="didLoadLatestConfiguration"){this.didGetLatestConfiguration=true;if(response.chainId){this.updateAccount(response.name,response.results,response.chainId,response.rpcURL)}var _iterator=_createForOfIteratorHelper(this.pendingPayloads),_step;try{for(_iterator.s();!(_step=_iterator.n()).done;){var payload=_step.value;this._processPayload(payload)}}catch(err){_iterator.e(err)}finally{_iterator.f()}this.pendingPayloads=[];return}if("result"in response){this.sendResponse(id,response.result)}else if("results"in response){if(response.name=="switchEthereumChain"||response.name=="addEthereumChain"){this.updateAccount(response.name,response.results,response.chainId,response.rpcURL)}if(response.name!="switchAccount"){this.sendResponse(id,response.results)}if(response.name=="requestAccounts"||response.name=="switchAccount"){this.updateAccount(response.name,response.results,response.chainId,response.rpcURL)}}else if("error"in response){this.sendError(id,response.error)}}},{key:"postMessage",value:function postMessage(handler,id,data){if(this.ready||handler==="requestAccounts"||handler==="switchEthereumChain"||handler==="addEthereumChain"){var object={object:data,address:this.address,networkId:this.net_version()};window.tokenary.postMessage(handler,id,object,"ethereum")}else{this.sendError(id,new _error["default"](4100,"provider is not ready"))}}},{key:"sendResponse",value:function sendResponse(id,result){var originId=this.idMapping.tryPopId(id)||id;var callback=this.callbacks.get(id);var wrapResult=this.wrapResults.get(id);var data={jsonrpc:"2.0",id:originId};if(result!==null&&result.jsonrpc&&result.result){data.result=result.result}else{data.result=result}if(callback){wrapResult?callback(null,data):callback(null,result);this.callbacks["delete"](id)}else{console.log("callback id: ".concat(id," not found"))}}},{key:"sendError",value:function sendError(id,error){console.log("<== ".concat(id," sendError ").concat(error));var callback=this.callbacks.get(id);if(callback){callback(error instanceof Error?error:new Error(error),null);this.callbacks["delete"](id)}}}]);return TokenaryEthereum}(_events.EventEmitter);module.exports=TokenaryEthereum},{"./error":1,"./id_mapping":3,"./rpc":10,"./utils":11,events:7,isutf8:9}],3:[function(require,module,exports){"use strict";var _utils=_interopRequireDefault(require("./utils"));function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(target,props){for(var i=0;i=o.length)return{done:true};return{done:false,value:o[i++]}},e:function e(_e){throw _e},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var normalCompletion=true,didErr=false,err;return{s:function s(){it=it.call(o)},n:function n(){var step=it.next();normalCompletion=step.done;return step},e:function e(_e2){didErr=true;err=_e2},f:function f(){try{if(!normalCompletion&&it["return"]!=null)it["return"]()}finally{if(didErr)throw err}}}}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i0){throw new Error("Invalid string. Length must be a multiple of 4")}var validLen=b64.indexOf("=");if(validLen===-1)validLen=len;var placeHoldersLen=validLen===len?0:4-validLen%4;return[validLen,placeHoldersLen]}function byteLength(b64){var lens=getLens(b64);var validLen=lens[0];var placeHoldersLen=lens[1];return(validLen+placeHoldersLen)*3/4-placeHoldersLen}function _byteLength(b64,validLen,placeHoldersLen){return(validLen+placeHoldersLen)*3/4-placeHoldersLen}function toByteArray(b64){var tmp;var lens=getLens(b64);var validLen=lens[0];var placeHoldersLen=lens[1];var arr=new Arr(_byteLength(b64,validLen,placeHoldersLen));var curByte=0;var len=placeHoldersLen>0?validLen-4:validLen;var i;for(i=0;i>16&255;arr[curByte++]=tmp>>8&255;arr[curByte++]=tmp&255}if(placeHoldersLen===2){tmp=revLookup[b64.charCodeAt(i)]<<2|revLookup[b64.charCodeAt(i+1)]>>4;arr[curByte++]=tmp&255}if(placeHoldersLen===1){tmp=revLookup[b64.charCodeAt(i)]<<10|revLookup[b64.charCodeAt(i+1)]<<4|revLookup[b64.charCodeAt(i+2)]>>2;arr[curByte++]=tmp>>8&255;arr[curByte++]=tmp&255}return arr}function tripletToBase64(num){return lookup[num>>18&63]+lookup[num>>12&63]+lookup[num>>6&63]+lookup[num&63]}function encodeChunk(uint8,start,end){var tmp;var output=[];for(var i=start;ilen2?len2:i+maxChunkLength))}if(extraBytes===1){tmp=uint8[len-1];parts.push(lookup[tmp>>2]+lookup[tmp<<4&63]+"==")}else if(extraBytes===2){tmp=(uint8[len-2]<<8)+uint8[len-1];parts.push(lookup[tmp>>10]+lookup[tmp>>4&63]+lookup[tmp<<2&63]+"=")}return parts.join("")}},{}],6:[function(require,module,exports){(function(Buffer){(function(){"use strict";var base64=require("base64-js");var ieee754=require("ieee754");exports.Buffer=Buffer;exports.SlowBuffer=SlowBuffer;exports.INSPECT_MAX_BYTES=50;var K_MAX_LENGTH=2147483647;exports.kMaxLength=K_MAX_LENGTH;Buffer.TYPED_ARRAY_SUPPORT=typedArraySupport();if(!Buffer.TYPED_ARRAY_SUPPORT&&typeof console!=="undefined"&&typeof console.error==="function"){console.error("This browser lacks typed array (Uint8Array) support which is required by "+"`buffer` v5.x. Use `buffer` v4.x if you require old browser support.")}function typedArraySupport(){try{var arr=new Uint8Array(1);arr.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}};return arr.foo()===42}catch(e){return false}}Object.defineProperty(Buffer.prototype,"parent",{enumerable:true,get:function(){if(!Buffer.isBuffer(this))return undefined;return this.buffer}});Object.defineProperty(Buffer.prototype,"offset",{enumerable:true,get:function(){if(!Buffer.isBuffer(this))return undefined;return this.byteOffset}});function createBuffer(length){if(length>K_MAX_LENGTH){throw new RangeError('The value "'+length+'" is invalid for option "size"')}var buf=new Uint8Array(length);buf.__proto__=Buffer.prototype;return buf}function Buffer(arg,encodingOrOffset,length){if(typeof arg==="number"){if(typeof encodingOrOffset==="string"){throw new TypeError('The "string" argument must be of type string. Received type number')}return allocUnsafe(arg)}return from(arg,encodingOrOffset,length)}if(typeof Symbol!=="undefined"&&Symbol.species!=null&&Buffer[Symbol.species]===Buffer){Object.defineProperty(Buffer,Symbol.species,{value:null,configurable:true,enumerable:false,writable:false})}Buffer.poolSize=8192;function from(value,encodingOrOffset,length){if(typeof value==="string"){return fromString(value,encodingOrOffset)}if(ArrayBuffer.isView(value)){return fromArrayLike(value)}if(value==null){throw TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, "+"or Array-like Object. Received type "+typeof value)}if(isInstance(value,ArrayBuffer)||value&&isInstance(value.buffer,ArrayBuffer)){return fromArrayBuffer(value,encodingOrOffset,length)}if(typeof value==="number"){throw new TypeError('The "value" argument must not be of type number. Received type number')}var valueOf=value.valueOf&&value.valueOf();if(valueOf!=null&&valueOf!==value){return Buffer.from(valueOf,encodingOrOffset,length)}var b=fromObject(value);if(b)return b;if(typeof Symbol!=="undefined"&&Symbol.toPrimitive!=null&&typeof value[Symbol.toPrimitive]==="function"){return Buffer.from(value[Symbol.toPrimitive]("string"),encodingOrOffset,length)}throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, "+"or Array-like Object. Received type "+typeof value)}Buffer.from=function(value,encodingOrOffset,length){return from(value,encodingOrOffset,length)};Buffer.prototype.__proto__=Uint8Array.prototype;Buffer.__proto__=Uint8Array;function assertSize(size){if(typeof size!=="number"){throw new TypeError('"size" argument must be of type number')}else if(size<0){throw new RangeError('The value "'+size+'" is invalid for option "size"')}}function alloc(size,fill,encoding){assertSize(size);if(size<=0){return createBuffer(size)}if(fill!==undefined){return typeof encoding==="string"?createBuffer(size).fill(fill,encoding):createBuffer(size).fill(fill)}return createBuffer(size)}Buffer.alloc=function(size,fill,encoding){return alloc(size,fill,encoding)};function allocUnsafe(size){assertSize(size);return createBuffer(size<0?0:checked(size)|0)}Buffer.allocUnsafe=function(size){return allocUnsafe(size)};Buffer.allocUnsafeSlow=function(size){return allocUnsafe(size)};function fromString(string,encoding){if(typeof encoding!=="string"||encoding===""){encoding="utf8"}if(!Buffer.isEncoding(encoding)){throw new TypeError("Unknown encoding: "+encoding)}var length=byteLength(string,encoding)|0;var buf=createBuffer(length);var actual=buf.write(string,encoding);if(actual!==length){buf=buf.slice(0,actual)}return buf}function fromArrayLike(array){var length=array.length<0?0:checked(array.length)|0;var buf=createBuffer(length);for(var i=0;i=K_MAX_LENGTH){throw new RangeError("Attempt to allocate Buffer larger than maximum "+"size: 0x"+K_MAX_LENGTH.toString(16)+" bytes")}return length|0}function SlowBuffer(length){if(+length!=length){length=0}return Buffer.alloc(+length)}Buffer.isBuffer=function isBuffer(b){return b!=null&&b._isBuffer===true&&b!==Buffer.prototype};Buffer.compare=function compare(a,b){if(isInstance(a,Uint8Array))a=Buffer.from(a,a.offset,a.byteLength);if(isInstance(b,Uint8Array))b=Buffer.from(b,b.offset,b.byteLength);if(!Buffer.isBuffer(a)||!Buffer.isBuffer(b)){throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array')}if(a===b)return 0;var x=a.length;var y=b.length;for(var i=0,len=Math.min(x,y);i2&&arguments[2]===true;if(!mustMatch&&len===0)return 0;var loweredCase=false;for(;;){switch(encoding){case"ascii":case"latin1":case"binary":return len;case"utf8":case"utf-8":return utf8ToBytes(string).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return len*2;case"hex":return len>>>1;case"base64":return base64ToBytes(string).length;default:if(loweredCase){return mustMatch?-1:utf8ToBytes(string).length}encoding=(""+encoding).toLowerCase();loweredCase=true}}}Buffer.byteLength=byteLength;function slowToString(encoding,start,end){var loweredCase=false;if(start===undefined||start<0){start=0}if(start>this.length){return""}if(end===undefined||end>this.length){end=this.length}if(end<=0){return""}end>>>=0;start>>>=0;if(end<=start){return""}if(!encoding)encoding="utf8";while(true){switch(encoding){case"hex":return hexSlice(this,start,end);case"utf8":case"utf-8":return utf8Slice(this,start,end);case"ascii":return asciiSlice(this,start,end);case"latin1":case"binary":return latin1Slice(this,start,end);case"base64":return base64Slice(this,start,end);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return utf16leSlice(this,start,end);default:if(loweredCase)throw new TypeError("Unknown encoding: "+encoding);encoding=(encoding+"").toLowerCase();loweredCase=true}}}Buffer.prototype._isBuffer=true;function swap(b,n,m){var i=b[n];b[n]=b[m];b[m]=i}Buffer.prototype.swap16=function swap16(){var len=this.length;if(len%2!==0){throw new RangeError("Buffer size must be a multiple of 16-bits")}for(var i=0;imax)str+=" ... ";return""};Buffer.prototype.compare=function compare(target,start,end,thisStart,thisEnd){if(isInstance(target,Uint8Array)){target=Buffer.from(target,target.offset,target.byteLength)}if(!Buffer.isBuffer(target)){throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. '+"Received type "+typeof target)}if(start===undefined){start=0}if(end===undefined){end=target?target.length:0}if(thisStart===undefined){thisStart=0}if(thisEnd===undefined){thisEnd=this.length}if(start<0||end>target.length||thisStart<0||thisEnd>this.length){throw new RangeError("out of range index")}if(thisStart>=thisEnd&&start>=end){return 0}if(thisStart>=thisEnd){return-1}if(start>=end){return 1}start>>>=0;end>>>=0;thisStart>>>=0;thisEnd>>>=0;if(this===target)return 0;var x=thisEnd-thisStart;var y=end-start;var len=Math.min(x,y);var thisCopy=this.slice(thisStart,thisEnd);var targetCopy=target.slice(start,end);for(var i=0;i2147483647){byteOffset=2147483647}else if(byteOffset<-2147483648){byteOffset=-2147483648}byteOffset=+byteOffset;if(numberIsNaN(byteOffset)){byteOffset=dir?0:buffer.length-1}if(byteOffset<0)byteOffset=buffer.length+byteOffset;if(byteOffset>=buffer.length){if(dir)return-1;else byteOffset=buffer.length-1}else if(byteOffset<0){if(dir)byteOffset=0;else return-1}if(typeof val==="string"){val=Buffer.from(val,encoding)}if(Buffer.isBuffer(val)){if(val.length===0){return-1}return arrayIndexOf(buffer,val,byteOffset,encoding,dir)}else if(typeof val==="number"){val=val&255;if(typeof Uint8Array.prototype.indexOf==="function"){if(dir){return Uint8Array.prototype.indexOf.call(buffer,val,byteOffset)}else{return Uint8Array.prototype.lastIndexOf.call(buffer,val,byteOffset)}}return arrayIndexOf(buffer,[val],byteOffset,encoding,dir)}throw new TypeError("val must be string, number or Buffer")}function arrayIndexOf(arr,val,byteOffset,encoding,dir){var indexSize=1;var arrLength=arr.length;var valLength=val.length;if(encoding!==undefined){encoding=String(encoding).toLowerCase();if(encoding==="ucs2"||encoding==="ucs-2"||encoding==="utf16le"||encoding==="utf-16le"){if(arr.length<2||val.length<2){return-1}indexSize=2;arrLength/=2;valLength/=2;byteOffset/=2}}function read(buf,i){if(indexSize===1){return buf[i]}else{return buf.readUInt16BE(i*indexSize)}}var i;if(dir){var foundIndex=-1;for(i=byteOffset;iarrLength)byteOffset=arrLength-valLength;for(i=byteOffset;i>=0;i--){var found=true;for(var j=0;jremaining){length=remaining}}var strLen=string.length;if(length>strLen/2){length=strLen/2}for(var i=0;i>>0;if(isFinite(length)){length=length>>>0;if(encoding===undefined)encoding="utf8"}else{encoding=length;length=undefined}}else{throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported")}var remaining=this.length-offset;if(length===undefined||length>remaining)length=remaining;if(string.length>0&&(length<0||offset<0)||offset>this.length){throw new RangeError("Attempt to write outside buffer bounds")}if(!encoding)encoding="utf8";var loweredCase=false;for(;;){switch(encoding){case"hex":return hexWrite(this,string,offset,length);case"utf8":case"utf-8":return utf8Write(this,string,offset,length);case"ascii":return asciiWrite(this,string,offset,length);case"latin1":case"binary":return latin1Write(this,string,offset,length);case"base64":return base64Write(this,string,offset,length);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return ucs2Write(this,string,offset,length);default:if(loweredCase)throw new TypeError("Unknown encoding: "+encoding);encoding=(""+encoding).toLowerCase();loweredCase=true}}};Buffer.prototype.toJSON=function toJSON(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function base64Slice(buf,start,end){if(start===0&&end===buf.length){return base64.fromByteArray(buf)}else{return base64.fromByteArray(buf.slice(start,end))}}function utf8Slice(buf,start,end){end=Math.min(buf.length,end);var res=[];var i=start;while(i239?4:firstByte>223?3:firstByte>191?2:1;if(i+bytesPerSequence<=end){var secondByte,thirdByte,fourthByte,tempCodePoint;switch(bytesPerSequence){case 1:if(firstByte<128){codePoint=firstByte}break;case 2:secondByte=buf[i+1];if((secondByte&192)===128){tempCodePoint=(firstByte&31)<<6|secondByte&63;if(tempCodePoint>127){codePoint=tempCodePoint}}break;case 3:secondByte=buf[i+1];thirdByte=buf[i+2];if((secondByte&192)===128&&(thirdByte&192)===128){tempCodePoint=(firstByte&15)<<12|(secondByte&63)<<6|thirdByte&63;if(tempCodePoint>2047&&(tempCodePoint<55296||tempCodePoint>57343)){codePoint=tempCodePoint}}break;case 4:secondByte=buf[i+1];thirdByte=buf[i+2];fourthByte=buf[i+3];if((secondByte&192)===128&&(thirdByte&192)===128&&(fourthByte&192)===128){tempCodePoint=(firstByte&15)<<18|(secondByte&63)<<12|(thirdByte&63)<<6|fourthByte&63;if(tempCodePoint>65535&&tempCodePoint<1114112){codePoint=tempCodePoint}}}}if(codePoint===null){codePoint=65533;bytesPerSequence=1}else if(codePoint>65535){codePoint-=65536;res.push(codePoint>>>10&1023|55296);codePoint=56320|codePoint&1023}res.push(codePoint);i+=bytesPerSequence}return decodeCodePointsArray(res)}var MAX_ARGUMENTS_LENGTH=4096;function decodeCodePointsArray(codePoints){var len=codePoints.length;if(len<=MAX_ARGUMENTS_LENGTH){return String.fromCharCode.apply(String,codePoints)}var res="";var i=0;while(ilen)end=len;var out="";for(var i=start;ilen){start=len}if(end<0){end+=len;if(end<0)end=0}else if(end>len){end=len}if(endlength)throw new RangeError("Trying to access beyond buffer length")}Buffer.prototype.readUIntLE=function readUIntLE(offset,byteLength,noAssert){offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert)checkOffset(offset,byteLength,this.length);var val=this[offset];var mul=1;var i=0;while(++i>>0;byteLength=byteLength>>>0;if(!noAssert){checkOffset(offset,byteLength,this.length)}var val=this[offset+--byteLength];var mul=1;while(byteLength>0&&(mul*=256)){val+=this[offset+--byteLength]*mul}return val};Buffer.prototype.readUInt8=function readUInt8(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,1,this.length);return this[offset]};Buffer.prototype.readUInt16LE=function readUInt16LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);return this[offset]|this[offset+1]<<8};Buffer.prototype.readUInt16BE=function readUInt16BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);return this[offset]<<8|this[offset+1]};Buffer.prototype.readUInt32LE=function readUInt32LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return(this[offset]|this[offset+1]<<8|this[offset+2]<<16)+this[offset+3]*16777216};Buffer.prototype.readUInt32BE=function readUInt32BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return this[offset]*16777216+(this[offset+1]<<16|this[offset+2]<<8|this[offset+3])};Buffer.prototype.readIntLE=function readIntLE(offset,byteLength,noAssert){offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert)checkOffset(offset,byteLength,this.length);var val=this[offset];var mul=1;var i=0;while(++i=mul)val-=Math.pow(2,8*byteLength);return val};Buffer.prototype.readIntBE=function readIntBE(offset,byteLength,noAssert){offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert)checkOffset(offset,byteLength,this.length);var i=byteLength;var mul=1;var val=this[offset+--i];while(i>0&&(mul*=256)){val+=this[offset+--i]*mul}mul*=128;if(val>=mul)val-=Math.pow(2,8*byteLength);return val};Buffer.prototype.readInt8=function readInt8(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,1,this.length);if(!(this[offset]&128))return this[offset];return(255-this[offset]+1)*-1};Buffer.prototype.readInt16LE=function readInt16LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);var val=this[offset]|this[offset+1]<<8;return val&32768?val|4294901760:val};Buffer.prototype.readInt16BE=function readInt16BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);var val=this[offset+1]|this[offset]<<8;return val&32768?val|4294901760:val};Buffer.prototype.readInt32LE=function readInt32LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return this[offset]|this[offset+1]<<8|this[offset+2]<<16|this[offset+3]<<24};Buffer.prototype.readInt32BE=function readInt32BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return this[offset]<<24|this[offset+1]<<16|this[offset+2]<<8|this[offset+3]};Buffer.prototype.readFloatLE=function readFloatLE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return ieee754.read(this,offset,true,23,4)};Buffer.prototype.readFloatBE=function readFloatBE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return ieee754.read(this,offset,false,23,4)};Buffer.prototype.readDoubleLE=function readDoubleLE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,8,this.length);return ieee754.read(this,offset,true,52,8)};Buffer.prototype.readDoubleBE=function readDoubleBE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,8,this.length);return ieee754.read(this,offset,false,52,8)};function checkInt(buf,value,offset,ext,max,min){if(!Buffer.isBuffer(buf))throw new TypeError('"buffer" argument must be a Buffer instance');if(value>max||valuebuf.length)throw new RangeError("Index out of range")}Buffer.prototype.writeUIntLE=function writeUIntLE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert){var maxBytes=Math.pow(2,8*byteLength)-1;checkInt(this,value,offset,byteLength,maxBytes,0)}var mul=1;var i=0;this[offset]=value&255;while(++i>>0;byteLength=byteLength>>>0;if(!noAssert){var maxBytes=Math.pow(2,8*byteLength)-1;checkInt(this,value,offset,byteLength,maxBytes,0)}var i=byteLength-1;var mul=1;this[offset+i]=value&255;while(--i>=0&&(mul*=256)){this[offset+i]=value/mul&255}return offset+byteLength};Buffer.prototype.writeUInt8=function writeUInt8(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,1,255,0);this[offset]=value&255;return offset+1};Buffer.prototype.writeUInt16LE=function writeUInt16LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,65535,0);this[offset]=value&255;this[offset+1]=value>>>8;return offset+2};Buffer.prototype.writeUInt16BE=function writeUInt16BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,65535,0);this[offset]=value>>>8;this[offset+1]=value&255;return offset+2};Buffer.prototype.writeUInt32LE=function writeUInt32LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,4294967295,0);this[offset+3]=value>>>24;this[offset+2]=value>>>16;this[offset+1]=value>>>8;this[offset]=value&255;return offset+4};Buffer.prototype.writeUInt32BE=function writeUInt32BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,4294967295,0);this[offset]=value>>>24;this[offset+1]=value>>>16;this[offset+2]=value>>>8;this[offset+3]=value&255;return offset+4};Buffer.prototype.writeIntLE=function writeIntLE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;if(!noAssert){var limit=Math.pow(2,8*byteLength-1);checkInt(this,value,offset,byteLength,limit-1,-limit)}var i=0;var mul=1;var sub=0;this[offset]=value&255;while(++i>0)-sub&255}return offset+byteLength};Buffer.prototype.writeIntBE=function writeIntBE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;if(!noAssert){var limit=Math.pow(2,8*byteLength-1);checkInt(this,value,offset,byteLength,limit-1,-limit)}var i=byteLength-1;var mul=1;var sub=0;this[offset+i]=value&255;while(--i>=0&&(mul*=256)){if(value<0&&sub===0&&this[offset+i+1]!==0){sub=1}this[offset+i]=(value/mul>>0)-sub&255}return offset+byteLength};Buffer.prototype.writeInt8=function writeInt8(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,1,127,-128);if(value<0)value=255+value+1;this[offset]=value&255;return offset+1};Buffer.prototype.writeInt16LE=function writeInt16LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,32767,-32768);this[offset]=value&255;this[offset+1]=value>>>8;return offset+2};Buffer.prototype.writeInt16BE=function writeInt16BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,32767,-32768);this[offset]=value>>>8;this[offset+1]=value&255;return offset+2};Buffer.prototype.writeInt32LE=function writeInt32LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,2147483647,-2147483648);this[offset]=value&255;this[offset+1]=value>>>8;this[offset+2]=value>>>16;this[offset+3]=value>>>24;return offset+4};Buffer.prototype.writeInt32BE=function writeInt32BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,2147483647,-2147483648);if(value<0)value=4294967295+value+1;this[offset]=value>>>24;this[offset+1]=value>>>16;this[offset+2]=value>>>8;this[offset+3]=value&255;return offset+4};function checkIEEE754(buf,value,offset,ext,max,min){if(offset+ext>buf.length)throw new RangeError("Index out of range");if(offset<0)throw new RangeError("Index out of range")}function writeFloat(buf,value,offset,littleEndian,noAssert){value=+value;offset=offset>>>0;if(!noAssert){checkIEEE754(buf,value,offset,4,34028234663852886e22,-34028234663852886e22)}ieee754.write(buf,value,offset,littleEndian,23,4);return offset+4}Buffer.prototype.writeFloatLE=function writeFloatLE(value,offset,noAssert){return writeFloat(this,value,offset,true,noAssert)};Buffer.prototype.writeFloatBE=function writeFloatBE(value,offset,noAssert){return writeFloat(this,value,offset,false,noAssert)};function writeDouble(buf,value,offset,littleEndian,noAssert){value=+value;offset=offset>>>0;if(!noAssert){checkIEEE754(buf,value,offset,8,17976931348623157e292,-17976931348623157e292)}ieee754.write(buf,value,offset,littleEndian,52,8);return offset+8}Buffer.prototype.writeDoubleLE=function writeDoubleLE(value,offset,noAssert){return writeDouble(this,value,offset,true,noAssert)};Buffer.prototype.writeDoubleBE=function writeDoubleBE(value,offset,noAssert){return writeDouble(this,value,offset,false,noAssert)};Buffer.prototype.copy=function copy(target,targetStart,start,end){if(!Buffer.isBuffer(target))throw new TypeError("argument should be a Buffer");if(!start)start=0;if(!end&&end!==0)end=this.length;if(targetStart>=target.length)targetStart=target.length;if(!targetStart)targetStart=0;if(end>0&&end=this.length)throw new RangeError("Index out of range");if(end<0)throw new RangeError("sourceEnd out of bounds");if(end>this.length)end=this.length;if(target.length-targetStart=0;--i){target[i+targetStart]=this[i+start]}}else{Uint8Array.prototype.set.call(target,this.subarray(start,end),targetStart)}return len};Buffer.prototype.fill=function fill(val,start,end,encoding){if(typeof val==="string"){if(typeof start==="string"){encoding=start;start=0;end=this.length}else if(typeof end==="string"){encoding=end;end=this.length}if(encoding!==undefined&&typeof encoding!=="string"){throw new TypeError("encoding must be a string")}if(typeof encoding==="string"&&!Buffer.isEncoding(encoding)){throw new TypeError("Unknown encoding: "+encoding)}if(val.length===1){var code=val.charCodeAt(0);if(encoding==="utf8"&&code<128||encoding==="latin1"){val=code}}}else if(typeof val==="number"){val=val&255}if(start<0||this.length>>0;end=end===undefined?this.length:end>>>0;if(!val)val=0;var i;if(typeof val==="number"){for(i=start;i55295&&codePoint<57344){if(!leadSurrogate){if(codePoint>56319){if((units-=3)>-1)bytes.push(239,191,189);continue}else if(i+1===length){if((units-=3)>-1)bytes.push(239,191,189);continue}leadSurrogate=codePoint;continue}if(codePoint<56320){if((units-=3)>-1)bytes.push(239,191,189);leadSurrogate=codePoint;continue}codePoint=(leadSurrogate-55296<<10|codePoint-56320)+65536}else if(leadSurrogate){if((units-=3)>-1)bytes.push(239,191,189)}leadSurrogate=null;if(codePoint<128){if((units-=1)<0)break;bytes.push(codePoint)}else if(codePoint<2048){if((units-=2)<0)break;bytes.push(codePoint>>6|192,codePoint&63|128)}else if(codePoint<65536){if((units-=3)<0)break;bytes.push(codePoint>>12|224,codePoint>>6&63|128,codePoint&63|128)}else if(codePoint<1114112){if((units-=4)<0)break;bytes.push(codePoint>>18|240,codePoint>>12&63|128,codePoint>>6&63|128,codePoint&63|128)}else{throw new Error("Invalid code point")}}return bytes}function asciiToBytes(str){var byteArray=[];for(var i=0;i>8;lo=c%256;byteArray.push(lo);byteArray.push(hi)}return byteArray}function base64ToBytes(str){return base64.toByteArray(base64clean(str))}function blitBuffer(src,dst,offset,length){for(var i=0;i=dst.length||i>=src.length)break;dst[i+offset]=src[i]}return i}function isInstance(obj,type){return obj instanceof type||obj!=null&&obj.constructor!=null&&obj.constructor.name!=null&&obj.constructor.name===type.name}function numberIsNaN(obj){return obj!==obj}}).call(this)}).call(this,require("buffer").Buffer)},{"base64-js":5,buffer:6,ieee754:8}],7:[function(require,module,exports){"use strict";var R=typeof Reflect==="object"?Reflect:null;var ReflectApply=R&&typeof R.apply==="function"?R.apply:function ReflectApply(target,receiver,args){return Function.prototype.apply.call(target,receiver,args)};var ReflectOwnKeys;if(R&&typeof R.ownKeys==="function"){ReflectOwnKeys=R.ownKeys}else if(Object.getOwnPropertySymbols){ReflectOwnKeys=function ReflectOwnKeys(target){return Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))}}else{ReflectOwnKeys=function ReflectOwnKeys(target){return Object.getOwnPropertyNames(target)}}function ProcessEmitWarning(warning){if(console&&console.warn)console.warn(warning)}var NumberIsNaN=Number.isNaN||function NumberIsNaN(value){return value!==value};function EventEmitter(){EventEmitter.init.call(this)}module.exports=EventEmitter;module.exports.once=once;EventEmitter.EventEmitter=EventEmitter;EventEmitter.prototype._events=undefined;EventEmitter.prototype._eventsCount=0;EventEmitter.prototype._maxListeners=undefined;var defaultMaxListeners=10;function checkListener(listener){if(typeof listener!=="function"){throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof listener)}}Object.defineProperty(EventEmitter,"defaultMaxListeners",{enumerable:true,get:function(){return defaultMaxListeners},set:function(arg){if(typeof arg!=="number"||arg<0||NumberIsNaN(arg)){throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+arg+".")}defaultMaxListeners=arg}});EventEmitter.init=function(){if(this._events===undefined||this._events===Object.getPrototypeOf(this)._events){this._events=Object.create(null);this._eventsCount=0}this._maxListeners=this._maxListeners||undefined};EventEmitter.prototype.setMaxListeners=function setMaxListeners(n){if(typeof n!=="number"||n<0||NumberIsNaN(n)){throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+n+".")}this._maxListeners=n;return this};function _getMaxListeners(that){if(that._maxListeners===undefined)return EventEmitter.defaultMaxListeners;return that._maxListeners}EventEmitter.prototype.getMaxListeners=function getMaxListeners(){return _getMaxListeners(this)};EventEmitter.prototype.emit=function emit(type){var args=[];for(var i=1;i0)er=args[0];if(er instanceof Error){throw er}var err=new Error("Unhandled error."+(er?" ("+er.message+")":""));err.context=er;throw err}var handler=events[type];if(handler===undefined)return false;if(typeof handler==="function"){ReflectApply(handler,this,args)}else{var len=handler.length;var listeners=arrayClone(handler,len);for(var i=0;i0&&existing.length>m&&!existing.warned){existing.warned=true;var w=new Error("Possible EventEmitter memory leak detected. "+existing.length+" "+String(type)+" listeners "+"added. Use emitter.setMaxListeners() to "+"increase limit");w.name="MaxListenersExceededWarning";w.emitter=target;w.type=type;w.count=existing.length;ProcessEmitWarning(w)}}return target}EventEmitter.prototype.addListener=function addListener(type,listener){return _addListener(this,type,listener,false)};EventEmitter.prototype.on=EventEmitter.prototype.addListener;EventEmitter.prototype.prependListener=function prependListener(type,listener){return _addListener(this,type,listener,true)};function onceWrapper(){if(!this.fired){this.target.removeListener(this.type,this.wrapFn);this.fired=true;if(arguments.length===0)return this.listener.call(this.target);return this.listener.apply(this.target,arguments)}}function _onceWrap(target,type,listener){var state={fired:false,wrapFn:undefined,target:target,type:type,listener:listener};var wrapped=onceWrapper.bind(state);wrapped.listener=listener;state.wrapFn=wrapped;return wrapped}EventEmitter.prototype.once=function once(type,listener){checkListener(listener);this.on(type,_onceWrap(this,type,listener));return this};EventEmitter.prototype.prependOnceListener=function prependOnceListener(type,listener){checkListener(listener);this.prependListener(type,_onceWrap(this,type,listener));return this};EventEmitter.prototype.removeListener=function removeListener(type,listener){var list,events,position,i,originalListener;checkListener(listener);events=this._events;if(events===undefined)return this;list=events[type];if(list===undefined)return this;if(list===listener||list.listener===listener){if(--this._eventsCount===0)this._events=Object.create(null);else{delete events[type];if(events.removeListener)this.emit("removeListener",type,list.listener||listener)}}else if(typeof list!=="function"){position=-1;for(i=list.length-1;i>=0;i--){if(list[i]===listener||list[i].listener===listener){originalListener=list[i].listener;position=i;break}}if(position<0)return this;if(position===0)list.shift();else{spliceOne(list,position)}if(list.length===1)events[type]=list[0];if(events.removeListener!==undefined)this.emit("removeListener",type,originalListener||listener)}return this};EventEmitter.prototype.off=EventEmitter.prototype.removeListener;EventEmitter.prototype.removeAllListeners=function removeAllListeners(type){var listeners,events,i;events=this._events;if(events===undefined)return this;if(events.removeListener===undefined){if(arguments.length===0){this._events=Object.create(null);this._eventsCount=0}else if(events[type]!==undefined){if(--this._eventsCount===0)this._events=Object.create(null);else delete events[type]}return this}if(arguments.length===0){var keys=Object.keys(events);var key;for(i=0;i=0;i--){this.removeListener(type,listeners[i])}}return this};function _listeners(target,type,unwrap){var events=target._events;if(events===undefined)return[];var evlistener=events[type];if(evlistener===undefined)return[];if(typeof evlistener==="function")return unwrap?[evlistener.listener||evlistener]:[evlistener];return unwrap?unwrapListeners(evlistener):arrayClone(evlistener,evlistener.length)}EventEmitter.prototype.listeners=function listeners(type){return _listeners(this,type,true)};EventEmitter.prototype.rawListeners=function rawListeners(type){return _listeners(this,type,false)};EventEmitter.listenerCount=function(emitter,type){if(typeof emitter.listenerCount==="function"){return emitter.listenerCount(type)}else{return listenerCount.call(emitter,type)}};EventEmitter.prototype.listenerCount=listenerCount;function listenerCount(type){var events=this._events;if(events!==undefined){var evlistener=events[type];if(typeof evlistener==="function"){return 1}else if(evlistener!==undefined){return evlistener.length}}return 0}EventEmitter.prototype.eventNames=function eventNames(){return this._eventsCount>0?ReflectOwnKeys(this._events):[]};function arrayClone(arr,n){var copy=new Array(n);for(var i=0;i>1;var nBits=-7;var i=isLE?nBytes-1:0;var d=isLE?-1:1;var s=buffer[offset+i];i+=d;e=s&(1<<-nBits)-1;s>>=-nBits;nBits+=eLen;for(;nBits>0;e=e*256+buffer[offset+i],i+=d,nBits-=8){}m=e&(1<<-nBits)-1;e>>=-nBits;nBits+=mLen;for(;nBits>0;m=m*256+buffer[offset+i],i+=d,nBits-=8){}if(e===0){e=1-eBias}else if(e===eMax){return m?NaN:(s?-1:1)*Infinity}else{m=m+Math.pow(2,mLen);e=e-eBias}return(s?-1:1)*m*Math.pow(2,e-mLen)};exports.write=function(buffer,value,offset,isLE,mLen,nBytes){var e,m,c;var eLen=nBytes*8-mLen-1;var eMax=(1<>1;var rt=mLen===23?Math.pow(2,-24)-Math.pow(2,-77):0;var i=isLE?0:nBytes-1;var d=isLE?1:-1;var s=value<0||value===0&&1/value<0?1:0;value=Math.abs(value);if(isNaN(value)||value===Infinity){m=isNaN(value)?1:0;e=eMax}else{e=Math.floor(Math.log(value)/Math.LN2);if(value*(c=Math.pow(2,-e))<1){e--;c*=2}if(e+eBias>=1){value+=rt/c}else{value+=rt*Math.pow(2,1-eBias)}if(value*c>=2){e++;c/=2}if(e+eBias>=eMax){m=0;e=eMax}else if(e+eBias>=1){m=(value*c-1)*Math.pow(2,mLen);e=e+eBias}else{m=value*Math.pow(2,eBias-1)*Math.pow(2,mLen);e=0}}for(;mLen>=8;buffer[offset+i]=m&255,i+=d,m/=256,mLen-=8){}e=e<0;buffer[offset+i]=e&255,i+=d,e/=256,eLen-=8){}buffer[offset+i-d]|=s*128}},{}],9:[function(require,module,exports){"use strict";function isUtf8(buf){if(!buf){return false}let i=0;const len=buf.length;while(i=194&&buf[i]<=223){if(buf[i+1]>>6===2){i+=2;continue}else{return false}}if((buf[i]===224&&buf[i+1]>=160&&buf[i+1]<=191||buf[i]===237&&buf[i+1]>=128&&buf[i+1]<=159)&&buf[i+2]>>6===2){i+=3;continue}if((buf[i]>=225&&buf[i]<=236||buf[i]>=238&&buf[i]<=239)&&buf[i+1]>>6===2&&buf[i+2]>>6===2){i+=3;continue}if((buf[i]===240&&buf[i+1]>=144&&buf[i+1]<=191||buf[i]>=241&&buf[i]<=243&&buf[i+1]>>6===2||buf[i]===244&&buf[i+1]>=128&&buf[i+1]<=143)&&buf[i+2]>>6===2&&buf[i+3]>>6===2){i+=4;continue}return false}return true}module.exports=isUtf8},{}],10:[function(require,module,exports){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(target,props){for(var i=0;iarr.length)len=arr.length;for(var i=0,arr2=new Array(len);i=to){return[]}return new Array(to-from).fill().map(function(_,i){return i+from})}},{key:"hexToInt",value:function hexToInt(hexString){if(hexString===undefined||hexString===null){return hexString}return Number.parseInt(hexString,16)}},{key:"intToHex",value:function intToHex(_int){if(_int===undefined||_int===null){return _int}var hexString=_int.toString(16);return"0x"+hexString}},{key:"messageToBuffer",value:function messageToBuffer(message){var buffer=_buffer.Buffer.from([]);try{if(typeof message==="string"){buffer=_buffer.Buffer.from(message.replace("0x",""),"hex")}else{buffer=_buffer.Buffer.from(message)}}catch(err){console.log("messageToBuffer error: ".concat(err))}return buffer}},{key:"bufferToHex",value:function bufferToHex(buf){return"0x"+_buffer.Buffer.from(buf).toString("hex")}}]);return Utils}();module.exports=Utils},{buffer:6}]},{},[4]); +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i=o.length)return{done:true};return{done:false,value:o[i++]}},e:function e(_e){throw _e},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var normalCompletion=true,didErr=false,err;return{s:function s(){it=it.call(o)},n:function n(){var step=it.next();normalCompletion=step.done;return step},e:function e(_e2){didErr=true;err=_e2},f:function f(){try{if(!normalCompletion&&it["return"]!=null)it["return"]()}finally{if(didErr)throw err}}}}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i1&&arguments[1]!==undefined?arguments[1]:true;this.idMapping.tryFixId(payload);return new Promise(function(resolve,reject){if(!payload.id){payload.id=_utils["default"].genId()}_this2.callbacks.set(payload.id,function(error,data){setTimeout(function(){if(error){reject(error)}else{resolve(data)}},1)});_this2.wrapResults.set(payload.id,wrapResult);switch(payload.method){case"eth_accounts":case"eth_coinbase":case"net_version":case"eth_chainId":case"eth_sign":case"personal_sign":case"personal_ecRecover":case"eth_signTypedData_v3":case"eth_signTypedData":case"eth_signTypedData_v4":case"eth_sendTransaction":case"eth_requestAccounts":case"wallet_addEthereumChain":case"wallet_switchEthereumChain":case"wallet_requestPermissions":case"wallet_getPermissions":return _this2._processPayload(payload);case"eth_newFilter":case"eth_newBlockFilter":case"eth_newPendingTransactionFilter":case"eth_uninstallFilter":case"eth_subscribe":throw new _error["default"](4200,"Tokenary does not support calling ".concat(payload.method,". Please use your own solution"));default:_this2.callbacks["delete"](payload.id);_this2.wrapResults["delete"](payload.id);return _this2.rpc.call(payload).then(function(response){wrapResult?resolve(response):resolve(response.result)})["catch"](reject)}})}},{key:"_processPayload",value:function _processPayload(payload){if(!this.didGetLatestConfiguration){this.pendingPayloads.push(payload);return}switch(payload.method){case"eth_accounts":return this.sendResponse(payload.id,this.eth_accounts());case"eth_coinbase":return this.sendResponse(payload.id,this.eth_coinbase());case"net_version":return this.sendResponse(payload.id,this.net_version());case"eth_chainId":return this.sendResponse(payload.id,this.eth_chainId());case"eth_sign":return this.eth_sign(payload);case"personal_sign":return this.personal_sign(payload);case"personal_ecRecover":return this.personal_ecRecover(payload);case"eth_signTypedData_v3":return this.eth_signTypedData(payload,false);case"eth_signTypedData":case"eth_signTypedData_v4":return this.eth_signTypedData(payload,true);case"eth_sendTransaction":return this.eth_sendTransaction(payload);case"eth_requestAccounts":if(!this.address){return this.eth_requestAccounts(payload)}else{return this.sendResponse(payload.id,this.eth_accounts())}case"wallet_addEthereumChain":return this.wallet_addEthereumChain(payload);case"wallet_switchEthereumChain":return this.wallet_switchEthereumChain(payload);case"wallet_requestPermissions":case"wallet_getPermissions":var permissions=[{parentCapability:"eth_accounts"}];return this.sendResponse(payload.id,permissions)}}},{key:"emitConnect",value:function emitConnect(chainId){this.emit("connect",{chainId:chainId})}},{key:"eth_accounts",value:function eth_accounts(){return this.address?[this.address]:[]}},{key:"eth_coinbase",value:function eth_coinbase(){return this.address}},{key:"net_version",value:function net_version(){return parseInt(this.chainId,16).toString(10)||null}},{key:"eth_chainId",value:function eth_chainId(){return this.chainId}},{key:"eth_sign",value:function eth_sign(payload){var buffer=_utils["default"].messageToBuffer(payload.params[1]);var hex=_utils["default"].bufferToHex(buffer);if((0,_isutf["default"])(buffer)){this.postMessage("signPersonalMessage",payload.id,{data:hex})}else{this.postMessage("signMessage",payload.id,{data:hex})}}},{key:"personal_sign",value:function personal_sign(payload){var message=payload.params[0];var buffer=_utils["default"].messageToBuffer(message);if(buffer.length===0){var hex=_utils["default"].bufferToHex(message);this.postMessage("signPersonalMessage",payload.id,{data:hex})}else{this.postMessage("signPersonalMessage",payload.id,{data:message})}}},{key:"personal_ecRecover",value:function personal_ecRecover(payload){this.postMessage("ecRecover",payload.id,{signature:payload.params[1],message:payload.params[0]})}},{key:"eth_signTypedData",value:function eth_signTypedData(payload,useV4){this.postMessage("signTypedMessage",payload.id,{raw:payload.params[1]})}},{key:"eth_sendTransaction",value:function eth_sendTransaction(payload){this.postMessage("signTransaction",payload.id,payload.params[0])}},{key:"eth_requestAccounts",value:function eth_requestAccounts(payload){this.postMessage("requestAccounts",payload.id,{})}},{key:"wallet_watchAsset",value:function wallet_watchAsset(payload){var options=payload.params.options;this.postMessage("watchAsset",payload.id,{type:payload.type,contract:options.address,symbol:options.symbol,decimals:options.decimals||0})}},{key:"wallet_switchEthereumChain",value:function wallet_switchEthereumChain(payload){if(this.chainId!=payload.params[0].chainId){this.postMessage("switchEthereumChain",payload.id,payload.params[0])}else{this.sendResponse(payload.id,[this.address])}}},{key:"wallet_addEthereumChain",value:function wallet_addEthereumChain(payload){this.postMessage("addEthereumChain",payload.id,payload.params[0])}},{key:"processTokenaryResponse",value:function processTokenaryResponse(id,response){if(response.name=="didLoadLatestConfiguration"){this.didGetLatestConfiguration=true;if(response.chainId){this.updateAccount(response.name,response.results,response.chainId,response.rpcURL)}var _iterator=_createForOfIteratorHelper(this.pendingPayloads),_step;try{for(_iterator.s();!(_step=_iterator.n()).done;){var payload=_step.value;this._processPayload(payload)}}catch(err){_iterator.e(err)}finally{_iterator.f()}this.pendingPayloads=[];return}if("result"in response){this.sendResponse(id,response.result)}else if("results"in response){if(response.name=="switchEthereumChain"||response.name=="addEthereumChain"){this.updateAccount(response.name,response.results,response.chainId,response.rpcURL)}if(response.name!="switchAccount"){this.sendResponse(id,response.results)}if(response.name=="requestAccounts"||response.name=="switchAccount"){this.updateAccount(response.name,response.results,response.chainId,response.rpcURL)}}else if("error"in response){this.sendError(id,response.error)}}},{key:"postMessage",value:function postMessage(handler,id,data){if(this.ready||handler==="requestAccounts"||handler==="switchEthereumChain"||handler==="addEthereumChain"){var object={object:data,address:this.address,chainId:this.chainId};window.tokenary.postMessage(handler,id,object,"ethereum")}else{this.sendError(id,new _error["default"](4100,"provider is not ready"))}}},{key:"sendResponse",value:function sendResponse(id,result){var originId=this.idMapping.tryPopId(id)||id;var callback=this.callbacks.get(id);var wrapResult=this.wrapResults.get(id);var data={jsonrpc:"2.0",id:originId};if(result!==null&&result.jsonrpc&&result.result){data.result=result.result}else{data.result=result}if(callback){wrapResult?callback(null,data):callback(null,result);this.callbacks["delete"](id)}else{console.log("callback id: ".concat(id," not found"))}}},{key:"sendError",value:function sendError(id,error){console.log("<== ".concat(id," sendError ").concat(error));var callback=this.callbacks.get(id);if(callback){callback(error instanceof Error?error:new Error(error),null);this.callbacks["delete"](id)}}}]);return TokenaryEthereum}(_events.EventEmitter);module.exports=TokenaryEthereum},{"./error":1,"./id_mapping":3,"./rpc":10,"./utils":11,events:7,isutf8:9}],3:[function(require,module,exports){"use strict";var _utils=_interopRequireDefault(require("./utils"));function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(target,props){for(var i=0;i=o.length)return{done:true};return{done:false,value:o[i++]}},e:function e(_e){throw _e},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var normalCompletion=true,didErr=false,err;return{s:function s(){it=it.call(o)},n:function n(){var step=it.next();normalCompletion=step.done;return step},e:function e(_e2){didErr=true;err=_e2},f:function f(){try{if(!normalCompletion&&it["return"]!=null)it["return"]()}finally{if(didErr)throw err}}}}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i0){throw new Error("Invalid string. Length must be a multiple of 4")}var validLen=b64.indexOf("=");if(validLen===-1)validLen=len;var placeHoldersLen=validLen===len?0:4-validLen%4;return[validLen,placeHoldersLen]}function byteLength(b64){var lens=getLens(b64);var validLen=lens[0];var placeHoldersLen=lens[1];return(validLen+placeHoldersLen)*3/4-placeHoldersLen}function _byteLength(b64,validLen,placeHoldersLen){return(validLen+placeHoldersLen)*3/4-placeHoldersLen}function toByteArray(b64){var tmp;var lens=getLens(b64);var validLen=lens[0];var placeHoldersLen=lens[1];var arr=new Arr(_byteLength(b64,validLen,placeHoldersLen));var curByte=0;var len=placeHoldersLen>0?validLen-4:validLen;var i;for(i=0;i>16&255;arr[curByte++]=tmp>>8&255;arr[curByte++]=tmp&255}if(placeHoldersLen===2){tmp=revLookup[b64.charCodeAt(i)]<<2|revLookup[b64.charCodeAt(i+1)]>>4;arr[curByte++]=tmp&255}if(placeHoldersLen===1){tmp=revLookup[b64.charCodeAt(i)]<<10|revLookup[b64.charCodeAt(i+1)]<<4|revLookup[b64.charCodeAt(i+2)]>>2;arr[curByte++]=tmp>>8&255;arr[curByte++]=tmp&255}return arr}function tripletToBase64(num){return lookup[num>>18&63]+lookup[num>>12&63]+lookup[num>>6&63]+lookup[num&63]}function encodeChunk(uint8,start,end){var tmp;var output=[];for(var i=start;ilen2?len2:i+maxChunkLength))}if(extraBytes===1){tmp=uint8[len-1];parts.push(lookup[tmp>>2]+lookup[tmp<<4&63]+"==")}else if(extraBytes===2){tmp=(uint8[len-2]<<8)+uint8[len-1];parts.push(lookup[tmp>>10]+lookup[tmp>>4&63]+lookup[tmp<<2&63]+"=")}return parts.join("")}},{}],6:[function(require,module,exports){(function(Buffer){(function(){"use strict";var base64=require("base64-js");var ieee754=require("ieee754");exports.Buffer=Buffer;exports.SlowBuffer=SlowBuffer;exports.INSPECT_MAX_BYTES=50;var K_MAX_LENGTH=2147483647;exports.kMaxLength=K_MAX_LENGTH;Buffer.TYPED_ARRAY_SUPPORT=typedArraySupport();if(!Buffer.TYPED_ARRAY_SUPPORT&&typeof console!=="undefined"&&typeof console.error==="function"){console.error("This browser lacks typed array (Uint8Array) support which is required by "+"`buffer` v5.x. Use `buffer` v4.x if you require old browser support.")}function typedArraySupport(){try{var arr=new Uint8Array(1);arr.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}};return arr.foo()===42}catch(e){return false}}Object.defineProperty(Buffer.prototype,"parent",{enumerable:true,get:function(){if(!Buffer.isBuffer(this))return undefined;return this.buffer}});Object.defineProperty(Buffer.prototype,"offset",{enumerable:true,get:function(){if(!Buffer.isBuffer(this))return undefined;return this.byteOffset}});function createBuffer(length){if(length>K_MAX_LENGTH){throw new RangeError('The value "'+length+'" is invalid for option "size"')}var buf=new Uint8Array(length);buf.__proto__=Buffer.prototype;return buf}function Buffer(arg,encodingOrOffset,length){if(typeof arg==="number"){if(typeof encodingOrOffset==="string"){throw new TypeError('The "string" argument must be of type string. Received type number')}return allocUnsafe(arg)}return from(arg,encodingOrOffset,length)}if(typeof Symbol!=="undefined"&&Symbol.species!=null&&Buffer[Symbol.species]===Buffer){Object.defineProperty(Buffer,Symbol.species,{value:null,configurable:true,enumerable:false,writable:false})}Buffer.poolSize=8192;function from(value,encodingOrOffset,length){if(typeof value==="string"){return fromString(value,encodingOrOffset)}if(ArrayBuffer.isView(value)){return fromArrayLike(value)}if(value==null){throw TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, "+"or Array-like Object. Received type "+typeof value)}if(isInstance(value,ArrayBuffer)||value&&isInstance(value.buffer,ArrayBuffer)){return fromArrayBuffer(value,encodingOrOffset,length)}if(typeof value==="number"){throw new TypeError('The "value" argument must not be of type number. Received type number')}var valueOf=value.valueOf&&value.valueOf();if(valueOf!=null&&valueOf!==value){return Buffer.from(valueOf,encodingOrOffset,length)}var b=fromObject(value);if(b)return b;if(typeof Symbol!=="undefined"&&Symbol.toPrimitive!=null&&typeof value[Symbol.toPrimitive]==="function"){return Buffer.from(value[Symbol.toPrimitive]("string"),encodingOrOffset,length)}throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, "+"or Array-like Object. Received type "+typeof value)}Buffer.from=function(value,encodingOrOffset,length){return from(value,encodingOrOffset,length)};Buffer.prototype.__proto__=Uint8Array.prototype;Buffer.__proto__=Uint8Array;function assertSize(size){if(typeof size!=="number"){throw new TypeError('"size" argument must be of type number')}else if(size<0){throw new RangeError('The value "'+size+'" is invalid for option "size"')}}function alloc(size,fill,encoding){assertSize(size);if(size<=0){return createBuffer(size)}if(fill!==undefined){return typeof encoding==="string"?createBuffer(size).fill(fill,encoding):createBuffer(size).fill(fill)}return createBuffer(size)}Buffer.alloc=function(size,fill,encoding){return alloc(size,fill,encoding)};function allocUnsafe(size){assertSize(size);return createBuffer(size<0?0:checked(size)|0)}Buffer.allocUnsafe=function(size){return allocUnsafe(size)};Buffer.allocUnsafeSlow=function(size){return allocUnsafe(size)};function fromString(string,encoding){if(typeof encoding!=="string"||encoding===""){encoding="utf8"}if(!Buffer.isEncoding(encoding)){throw new TypeError("Unknown encoding: "+encoding)}var length=byteLength(string,encoding)|0;var buf=createBuffer(length);var actual=buf.write(string,encoding);if(actual!==length){buf=buf.slice(0,actual)}return buf}function fromArrayLike(array){var length=array.length<0?0:checked(array.length)|0;var buf=createBuffer(length);for(var i=0;i=K_MAX_LENGTH){throw new RangeError("Attempt to allocate Buffer larger than maximum "+"size: 0x"+K_MAX_LENGTH.toString(16)+" bytes")}return length|0}function SlowBuffer(length){if(+length!=length){length=0}return Buffer.alloc(+length)}Buffer.isBuffer=function isBuffer(b){return b!=null&&b._isBuffer===true&&b!==Buffer.prototype};Buffer.compare=function compare(a,b){if(isInstance(a,Uint8Array))a=Buffer.from(a,a.offset,a.byteLength);if(isInstance(b,Uint8Array))b=Buffer.from(b,b.offset,b.byteLength);if(!Buffer.isBuffer(a)||!Buffer.isBuffer(b)){throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array')}if(a===b)return 0;var x=a.length;var y=b.length;for(var i=0,len=Math.min(x,y);i2&&arguments[2]===true;if(!mustMatch&&len===0)return 0;var loweredCase=false;for(;;){switch(encoding){case"ascii":case"latin1":case"binary":return len;case"utf8":case"utf-8":return utf8ToBytes(string).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return len*2;case"hex":return len>>>1;case"base64":return base64ToBytes(string).length;default:if(loweredCase){return mustMatch?-1:utf8ToBytes(string).length}encoding=(""+encoding).toLowerCase();loweredCase=true}}}Buffer.byteLength=byteLength;function slowToString(encoding,start,end){var loweredCase=false;if(start===undefined||start<0){start=0}if(start>this.length){return""}if(end===undefined||end>this.length){end=this.length}if(end<=0){return""}end>>>=0;start>>>=0;if(end<=start){return""}if(!encoding)encoding="utf8";while(true){switch(encoding){case"hex":return hexSlice(this,start,end);case"utf8":case"utf-8":return utf8Slice(this,start,end);case"ascii":return asciiSlice(this,start,end);case"latin1":case"binary":return latin1Slice(this,start,end);case"base64":return base64Slice(this,start,end);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return utf16leSlice(this,start,end);default:if(loweredCase)throw new TypeError("Unknown encoding: "+encoding);encoding=(encoding+"").toLowerCase();loweredCase=true}}}Buffer.prototype._isBuffer=true;function swap(b,n,m){var i=b[n];b[n]=b[m];b[m]=i}Buffer.prototype.swap16=function swap16(){var len=this.length;if(len%2!==0){throw new RangeError("Buffer size must be a multiple of 16-bits")}for(var i=0;imax)str+=" ... ";return""};Buffer.prototype.compare=function compare(target,start,end,thisStart,thisEnd){if(isInstance(target,Uint8Array)){target=Buffer.from(target,target.offset,target.byteLength)}if(!Buffer.isBuffer(target)){throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. '+"Received type "+typeof target)}if(start===undefined){start=0}if(end===undefined){end=target?target.length:0}if(thisStart===undefined){thisStart=0}if(thisEnd===undefined){thisEnd=this.length}if(start<0||end>target.length||thisStart<0||thisEnd>this.length){throw new RangeError("out of range index")}if(thisStart>=thisEnd&&start>=end){return 0}if(thisStart>=thisEnd){return-1}if(start>=end){return 1}start>>>=0;end>>>=0;thisStart>>>=0;thisEnd>>>=0;if(this===target)return 0;var x=thisEnd-thisStart;var y=end-start;var len=Math.min(x,y);var thisCopy=this.slice(thisStart,thisEnd);var targetCopy=target.slice(start,end);for(var i=0;i2147483647){byteOffset=2147483647}else if(byteOffset<-2147483648){byteOffset=-2147483648}byteOffset=+byteOffset;if(numberIsNaN(byteOffset)){byteOffset=dir?0:buffer.length-1}if(byteOffset<0)byteOffset=buffer.length+byteOffset;if(byteOffset>=buffer.length){if(dir)return-1;else byteOffset=buffer.length-1}else if(byteOffset<0){if(dir)byteOffset=0;else return-1}if(typeof val==="string"){val=Buffer.from(val,encoding)}if(Buffer.isBuffer(val)){if(val.length===0){return-1}return arrayIndexOf(buffer,val,byteOffset,encoding,dir)}else if(typeof val==="number"){val=val&255;if(typeof Uint8Array.prototype.indexOf==="function"){if(dir){return Uint8Array.prototype.indexOf.call(buffer,val,byteOffset)}else{return Uint8Array.prototype.lastIndexOf.call(buffer,val,byteOffset)}}return arrayIndexOf(buffer,[val],byteOffset,encoding,dir)}throw new TypeError("val must be string, number or Buffer")}function arrayIndexOf(arr,val,byteOffset,encoding,dir){var indexSize=1;var arrLength=arr.length;var valLength=val.length;if(encoding!==undefined){encoding=String(encoding).toLowerCase();if(encoding==="ucs2"||encoding==="ucs-2"||encoding==="utf16le"||encoding==="utf-16le"){if(arr.length<2||val.length<2){return-1}indexSize=2;arrLength/=2;valLength/=2;byteOffset/=2}}function read(buf,i){if(indexSize===1){return buf[i]}else{return buf.readUInt16BE(i*indexSize)}}var i;if(dir){var foundIndex=-1;for(i=byteOffset;iarrLength)byteOffset=arrLength-valLength;for(i=byteOffset;i>=0;i--){var found=true;for(var j=0;jremaining){length=remaining}}var strLen=string.length;if(length>strLen/2){length=strLen/2}for(var i=0;i>>0;if(isFinite(length)){length=length>>>0;if(encoding===undefined)encoding="utf8"}else{encoding=length;length=undefined}}else{throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported")}var remaining=this.length-offset;if(length===undefined||length>remaining)length=remaining;if(string.length>0&&(length<0||offset<0)||offset>this.length){throw new RangeError("Attempt to write outside buffer bounds")}if(!encoding)encoding="utf8";var loweredCase=false;for(;;){switch(encoding){case"hex":return hexWrite(this,string,offset,length);case"utf8":case"utf-8":return utf8Write(this,string,offset,length);case"ascii":return asciiWrite(this,string,offset,length);case"latin1":case"binary":return latin1Write(this,string,offset,length);case"base64":return base64Write(this,string,offset,length);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return ucs2Write(this,string,offset,length);default:if(loweredCase)throw new TypeError("Unknown encoding: "+encoding);encoding=(""+encoding).toLowerCase();loweredCase=true}}};Buffer.prototype.toJSON=function toJSON(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function base64Slice(buf,start,end){if(start===0&&end===buf.length){return base64.fromByteArray(buf)}else{return base64.fromByteArray(buf.slice(start,end))}}function utf8Slice(buf,start,end){end=Math.min(buf.length,end);var res=[];var i=start;while(i239?4:firstByte>223?3:firstByte>191?2:1;if(i+bytesPerSequence<=end){var secondByte,thirdByte,fourthByte,tempCodePoint;switch(bytesPerSequence){case 1:if(firstByte<128){codePoint=firstByte}break;case 2:secondByte=buf[i+1];if((secondByte&192)===128){tempCodePoint=(firstByte&31)<<6|secondByte&63;if(tempCodePoint>127){codePoint=tempCodePoint}}break;case 3:secondByte=buf[i+1];thirdByte=buf[i+2];if((secondByte&192)===128&&(thirdByte&192)===128){tempCodePoint=(firstByte&15)<<12|(secondByte&63)<<6|thirdByte&63;if(tempCodePoint>2047&&(tempCodePoint<55296||tempCodePoint>57343)){codePoint=tempCodePoint}}break;case 4:secondByte=buf[i+1];thirdByte=buf[i+2];fourthByte=buf[i+3];if((secondByte&192)===128&&(thirdByte&192)===128&&(fourthByte&192)===128){tempCodePoint=(firstByte&15)<<18|(secondByte&63)<<12|(thirdByte&63)<<6|fourthByte&63;if(tempCodePoint>65535&&tempCodePoint<1114112){codePoint=tempCodePoint}}}}if(codePoint===null){codePoint=65533;bytesPerSequence=1}else if(codePoint>65535){codePoint-=65536;res.push(codePoint>>>10&1023|55296);codePoint=56320|codePoint&1023}res.push(codePoint);i+=bytesPerSequence}return decodeCodePointsArray(res)}var MAX_ARGUMENTS_LENGTH=4096;function decodeCodePointsArray(codePoints){var len=codePoints.length;if(len<=MAX_ARGUMENTS_LENGTH){return String.fromCharCode.apply(String,codePoints)}var res="";var i=0;while(ilen)end=len;var out="";for(var i=start;ilen){start=len}if(end<0){end+=len;if(end<0)end=0}else if(end>len){end=len}if(endlength)throw new RangeError("Trying to access beyond buffer length")}Buffer.prototype.readUIntLE=function readUIntLE(offset,byteLength,noAssert){offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert)checkOffset(offset,byteLength,this.length);var val=this[offset];var mul=1;var i=0;while(++i>>0;byteLength=byteLength>>>0;if(!noAssert){checkOffset(offset,byteLength,this.length)}var val=this[offset+--byteLength];var mul=1;while(byteLength>0&&(mul*=256)){val+=this[offset+--byteLength]*mul}return val};Buffer.prototype.readUInt8=function readUInt8(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,1,this.length);return this[offset]};Buffer.prototype.readUInt16LE=function readUInt16LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);return this[offset]|this[offset+1]<<8};Buffer.prototype.readUInt16BE=function readUInt16BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);return this[offset]<<8|this[offset+1]};Buffer.prototype.readUInt32LE=function readUInt32LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return(this[offset]|this[offset+1]<<8|this[offset+2]<<16)+this[offset+3]*16777216};Buffer.prototype.readUInt32BE=function readUInt32BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return this[offset]*16777216+(this[offset+1]<<16|this[offset+2]<<8|this[offset+3])};Buffer.prototype.readIntLE=function readIntLE(offset,byteLength,noAssert){offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert)checkOffset(offset,byteLength,this.length);var val=this[offset];var mul=1;var i=0;while(++i=mul)val-=Math.pow(2,8*byteLength);return val};Buffer.prototype.readIntBE=function readIntBE(offset,byteLength,noAssert){offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert)checkOffset(offset,byteLength,this.length);var i=byteLength;var mul=1;var val=this[offset+--i];while(i>0&&(mul*=256)){val+=this[offset+--i]*mul}mul*=128;if(val>=mul)val-=Math.pow(2,8*byteLength);return val};Buffer.prototype.readInt8=function readInt8(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,1,this.length);if(!(this[offset]&128))return this[offset];return(255-this[offset]+1)*-1};Buffer.prototype.readInt16LE=function readInt16LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);var val=this[offset]|this[offset+1]<<8;return val&32768?val|4294901760:val};Buffer.prototype.readInt16BE=function readInt16BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);var val=this[offset+1]|this[offset]<<8;return val&32768?val|4294901760:val};Buffer.prototype.readInt32LE=function readInt32LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return this[offset]|this[offset+1]<<8|this[offset+2]<<16|this[offset+3]<<24};Buffer.prototype.readInt32BE=function readInt32BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return this[offset]<<24|this[offset+1]<<16|this[offset+2]<<8|this[offset+3]};Buffer.prototype.readFloatLE=function readFloatLE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return ieee754.read(this,offset,true,23,4)};Buffer.prototype.readFloatBE=function readFloatBE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return ieee754.read(this,offset,false,23,4)};Buffer.prototype.readDoubleLE=function readDoubleLE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,8,this.length);return ieee754.read(this,offset,true,52,8)};Buffer.prototype.readDoubleBE=function readDoubleBE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,8,this.length);return ieee754.read(this,offset,false,52,8)};function checkInt(buf,value,offset,ext,max,min){if(!Buffer.isBuffer(buf))throw new TypeError('"buffer" argument must be a Buffer instance');if(value>max||valuebuf.length)throw new RangeError("Index out of range")}Buffer.prototype.writeUIntLE=function writeUIntLE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert){var maxBytes=Math.pow(2,8*byteLength)-1;checkInt(this,value,offset,byteLength,maxBytes,0)}var mul=1;var i=0;this[offset]=value&255;while(++i>>0;byteLength=byteLength>>>0;if(!noAssert){var maxBytes=Math.pow(2,8*byteLength)-1;checkInt(this,value,offset,byteLength,maxBytes,0)}var i=byteLength-1;var mul=1;this[offset+i]=value&255;while(--i>=0&&(mul*=256)){this[offset+i]=value/mul&255}return offset+byteLength};Buffer.prototype.writeUInt8=function writeUInt8(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,1,255,0);this[offset]=value&255;return offset+1};Buffer.prototype.writeUInt16LE=function writeUInt16LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,65535,0);this[offset]=value&255;this[offset+1]=value>>>8;return offset+2};Buffer.prototype.writeUInt16BE=function writeUInt16BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,65535,0);this[offset]=value>>>8;this[offset+1]=value&255;return offset+2};Buffer.prototype.writeUInt32LE=function writeUInt32LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,4294967295,0);this[offset+3]=value>>>24;this[offset+2]=value>>>16;this[offset+1]=value>>>8;this[offset]=value&255;return offset+4};Buffer.prototype.writeUInt32BE=function writeUInt32BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,4294967295,0);this[offset]=value>>>24;this[offset+1]=value>>>16;this[offset+2]=value>>>8;this[offset+3]=value&255;return offset+4};Buffer.prototype.writeIntLE=function writeIntLE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;if(!noAssert){var limit=Math.pow(2,8*byteLength-1);checkInt(this,value,offset,byteLength,limit-1,-limit)}var i=0;var mul=1;var sub=0;this[offset]=value&255;while(++i>0)-sub&255}return offset+byteLength};Buffer.prototype.writeIntBE=function writeIntBE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;if(!noAssert){var limit=Math.pow(2,8*byteLength-1);checkInt(this,value,offset,byteLength,limit-1,-limit)}var i=byteLength-1;var mul=1;var sub=0;this[offset+i]=value&255;while(--i>=0&&(mul*=256)){if(value<0&&sub===0&&this[offset+i+1]!==0){sub=1}this[offset+i]=(value/mul>>0)-sub&255}return offset+byteLength};Buffer.prototype.writeInt8=function writeInt8(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,1,127,-128);if(value<0)value=255+value+1;this[offset]=value&255;return offset+1};Buffer.prototype.writeInt16LE=function writeInt16LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,32767,-32768);this[offset]=value&255;this[offset+1]=value>>>8;return offset+2};Buffer.prototype.writeInt16BE=function writeInt16BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,32767,-32768);this[offset]=value>>>8;this[offset+1]=value&255;return offset+2};Buffer.prototype.writeInt32LE=function writeInt32LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,2147483647,-2147483648);this[offset]=value&255;this[offset+1]=value>>>8;this[offset+2]=value>>>16;this[offset+3]=value>>>24;return offset+4};Buffer.prototype.writeInt32BE=function writeInt32BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,2147483647,-2147483648);if(value<0)value=4294967295+value+1;this[offset]=value>>>24;this[offset+1]=value>>>16;this[offset+2]=value>>>8;this[offset+3]=value&255;return offset+4};function checkIEEE754(buf,value,offset,ext,max,min){if(offset+ext>buf.length)throw new RangeError("Index out of range");if(offset<0)throw new RangeError("Index out of range")}function writeFloat(buf,value,offset,littleEndian,noAssert){value=+value;offset=offset>>>0;if(!noAssert){checkIEEE754(buf,value,offset,4,34028234663852886e22,-34028234663852886e22)}ieee754.write(buf,value,offset,littleEndian,23,4);return offset+4}Buffer.prototype.writeFloatLE=function writeFloatLE(value,offset,noAssert){return writeFloat(this,value,offset,true,noAssert)};Buffer.prototype.writeFloatBE=function writeFloatBE(value,offset,noAssert){return writeFloat(this,value,offset,false,noAssert)};function writeDouble(buf,value,offset,littleEndian,noAssert){value=+value;offset=offset>>>0;if(!noAssert){checkIEEE754(buf,value,offset,8,17976931348623157e292,-17976931348623157e292)}ieee754.write(buf,value,offset,littleEndian,52,8);return offset+8}Buffer.prototype.writeDoubleLE=function writeDoubleLE(value,offset,noAssert){return writeDouble(this,value,offset,true,noAssert)};Buffer.prototype.writeDoubleBE=function writeDoubleBE(value,offset,noAssert){return writeDouble(this,value,offset,false,noAssert)};Buffer.prototype.copy=function copy(target,targetStart,start,end){if(!Buffer.isBuffer(target))throw new TypeError("argument should be a Buffer");if(!start)start=0;if(!end&&end!==0)end=this.length;if(targetStart>=target.length)targetStart=target.length;if(!targetStart)targetStart=0;if(end>0&&end=this.length)throw new RangeError("Index out of range");if(end<0)throw new RangeError("sourceEnd out of bounds");if(end>this.length)end=this.length;if(target.length-targetStart=0;--i){target[i+targetStart]=this[i+start]}}else{Uint8Array.prototype.set.call(target,this.subarray(start,end),targetStart)}return len};Buffer.prototype.fill=function fill(val,start,end,encoding){if(typeof val==="string"){if(typeof start==="string"){encoding=start;start=0;end=this.length}else if(typeof end==="string"){encoding=end;end=this.length}if(encoding!==undefined&&typeof encoding!=="string"){throw new TypeError("encoding must be a string")}if(typeof encoding==="string"&&!Buffer.isEncoding(encoding)){throw new TypeError("Unknown encoding: "+encoding)}if(val.length===1){var code=val.charCodeAt(0);if(encoding==="utf8"&&code<128||encoding==="latin1"){val=code}}}else if(typeof val==="number"){val=val&255}if(start<0||this.length>>0;end=end===undefined?this.length:end>>>0;if(!val)val=0;var i;if(typeof val==="number"){for(i=start;i55295&&codePoint<57344){if(!leadSurrogate){if(codePoint>56319){if((units-=3)>-1)bytes.push(239,191,189);continue}else if(i+1===length){if((units-=3)>-1)bytes.push(239,191,189);continue}leadSurrogate=codePoint;continue}if(codePoint<56320){if((units-=3)>-1)bytes.push(239,191,189);leadSurrogate=codePoint;continue}codePoint=(leadSurrogate-55296<<10|codePoint-56320)+65536}else if(leadSurrogate){if((units-=3)>-1)bytes.push(239,191,189)}leadSurrogate=null;if(codePoint<128){if((units-=1)<0)break;bytes.push(codePoint)}else if(codePoint<2048){if((units-=2)<0)break;bytes.push(codePoint>>6|192,codePoint&63|128)}else if(codePoint<65536){if((units-=3)<0)break;bytes.push(codePoint>>12|224,codePoint>>6&63|128,codePoint&63|128)}else if(codePoint<1114112){if((units-=4)<0)break;bytes.push(codePoint>>18|240,codePoint>>12&63|128,codePoint>>6&63|128,codePoint&63|128)}else{throw new Error("Invalid code point")}}return bytes}function asciiToBytes(str){var byteArray=[];for(var i=0;i>8;lo=c%256;byteArray.push(lo);byteArray.push(hi)}return byteArray}function base64ToBytes(str){return base64.toByteArray(base64clean(str))}function blitBuffer(src,dst,offset,length){for(var i=0;i=dst.length||i>=src.length)break;dst[i+offset]=src[i]}return i}function isInstance(obj,type){return obj instanceof type||obj!=null&&obj.constructor!=null&&obj.constructor.name!=null&&obj.constructor.name===type.name}function numberIsNaN(obj){return obj!==obj}}).call(this)}).call(this,require("buffer").Buffer)},{"base64-js":5,buffer:6,ieee754:8}],7:[function(require,module,exports){"use strict";var R=typeof Reflect==="object"?Reflect:null;var ReflectApply=R&&typeof R.apply==="function"?R.apply:function ReflectApply(target,receiver,args){return Function.prototype.apply.call(target,receiver,args)};var ReflectOwnKeys;if(R&&typeof R.ownKeys==="function"){ReflectOwnKeys=R.ownKeys}else if(Object.getOwnPropertySymbols){ReflectOwnKeys=function ReflectOwnKeys(target){return Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))}}else{ReflectOwnKeys=function ReflectOwnKeys(target){return Object.getOwnPropertyNames(target)}}function ProcessEmitWarning(warning){if(console&&console.warn)console.warn(warning)}var NumberIsNaN=Number.isNaN||function NumberIsNaN(value){return value!==value};function EventEmitter(){EventEmitter.init.call(this)}module.exports=EventEmitter;module.exports.once=once;EventEmitter.EventEmitter=EventEmitter;EventEmitter.prototype._events=undefined;EventEmitter.prototype._eventsCount=0;EventEmitter.prototype._maxListeners=undefined;var defaultMaxListeners=10;function checkListener(listener){if(typeof listener!=="function"){throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof listener)}}Object.defineProperty(EventEmitter,"defaultMaxListeners",{enumerable:true,get:function(){return defaultMaxListeners},set:function(arg){if(typeof arg!=="number"||arg<0||NumberIsNaN(arg)){throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+arg+".")}defaultMaxListeners=arg}});EventEmitter.init=function(){if(this._events===undefined||this._events===Object.getPrototypeOf(this)._events){this._events=Object.create(null);this._eventsCount=0}this._maxListeners=this._maxListeners||undefined};EventEmitter.prototype.setMaxListeners=function setMaxListeners(n){if(typeof n!=="number"||n<0||NumberIsNaN(n)){throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+n+".")}this._maxListeners=n;return this};function _getMaxListeners(that){if(that._maxListeners===undefined)return EventEmitter.defaultMaxListeners;return that._maxListeners}EventEmitter.prototype.getMaxListeners=function getMaxListeners(){return _getMaxListeners(this)};EventEmitter.prototype.emit=function emit(type){var args=[];for(var i=1;i0)er=args[0];if(er instanceof Error){throw er}var err=new Error("Unhandled error."+(er?" ("+er.message+")":""));err.context=er;throw err}var handler=events[type];if(handler===undefined)return false;if(typeof handler==="function"){ReflectApply(handler,this,args)}else{var len=handler.length;var listeners=arrayClone(handler,len);for(var i=0;i0&&existing.length>m&&!existing.warned){existing.warned=true;var w=new Error("Possible EventEmitter memory leak detected. "+existing.length+" "+String(type)+" listeners "+"added. Use emitter.setMaxListeners() to "+"increase limit");w.name="MaxListenersExceededWarning";w.emitter=target;w.type=type;w.count=existing.length;ProcessEmitWarning(w)}}return target}EventEmitter.prototype.addListener=function addListener(type,listener){return _addListener(this,type,listener,false)};EventEmitter.prototype.on=EventEmitter.prototype.addListener;EventEmitter.prototype.prependListener=function prependListener(type,listener){return _addListener(this,type,listener,true)};function onceWrapper(){if(!this.fired){this.target.removeListener(this.type,this.wrapFn);this.fired=true;if(arguments.length===0)return this.listener.call(this.target);return this.listener.apply(this.target,arguments)}}function _onceWrap(target,type,listener){var state={fired:false,wrapFn:undefined,target:target,type:type,listener:listener};var wrapped=onceWrapper.bind(state);wrapped.listener=listener;state.wrapFn=wrapped;return wrapped}EventEmitter.prototype.once=function once(type,listener){checkListener(listener);this.on(type,_onceWrap(this,type,listener));return this};EventEmitter.prototype.prependOnceListener=function prependOnceListener(type,listener){checkListener(listener);this.prependListener(type,_onceWrap(this,type,listener));return this};EventEmitter.prototype.removeListener=function removeListener(type,listener){var list,events,position,i,originalListener;checkListener(listener);events=this._events;if(events===undefined)return this;list=events[type];if(list===undefined)return this;if(list===listener||list.listener===listener){if(--this._eventsCount===0)this._events=Object.create(null);else{delete events[type];if(events.removeListener)this.emit("removeListener",type,list.listener||listener)}}else if(typeof list!=="function"){position=-1;for(i=list.length-1;i>=0;i--){if(list[i]===listener||list[i].listener===listener){originalListener=list[i].listener;position=i;break}}if(position<0)return this;if(position===0)list.shift();else{spliceOne(list,position)}if(list.length===1)events[type]=list[0];if(events.removeListener!==undefined)this.emit("removeListener",type,originalListener||listener)}return this};EventEmitter.prototype.off=EventEmitter.prototype.removeListener;EventEmitter.prototype.removeAllListeners=function removeAllListeners(type){var listeners,events,i;events=this._events;if(events===undefined)return this;if(events.removeListener===undefined){if(arguments.length===0){this._events=Object.create(null);this._eventsCount=0}else if(events[type]!==undefined){if(--this._eventsCount===0)this._events=Object.create(null);else delete events[type]}return this}if(arguments.length===0){var keys=Object.keys(events);var key;for(i=0;i=0;i--){this.removeListener(type,listeners[i])}}return this};function _listeners(target,type,unwrap){var events=target._events;if(events===undefined)return[];var evlistener=events[type];if(evlistener===undefined)return[];if(typeof evlistener==="function")return unwrap?[evlistener.listener||evlistener]:[evlistener];return unwrap?unwrapListeners(evlistener):arrayClone(evlistener,evlistener.length)}EventEmitter.prototype.listeners=function listeners(type){return _listeners(this,type,true)};EventEmitter.prototype.rawListeners=function rawListeners(type){return _listeners(this,type,false)};EventEmitter.listenerCount=function(emitter,type){if(typeof emitter.listenerCount==="function"){return emitter.listenerCount(type)}else{return listenerCount.call(emitter,type)}};EventEmitter.prototype.listenerCount=listenerCount;function listenerCount(type){var events=this._events;if(events!==undefined){var evlistener=events[type];if(typeof evlistener==="function"){return 1}else if(evlistener!==undefined){return evlistener.length}}return 0}EventEmitter.prototype.eventNames=function eventNames(){return this._eventsCount>0?ReflectOwnKeys(this._events):[]};function arrayClone(arr,n){var copy=new Array(n);for(var i=0;i>1;var nBits=-7;var i=isLE?nBytes-1:0;var d=isLE?-1:1;var s=buffer[offset+i];i+=d;e=s&(1<<-nBits)-1;s>>=-nBits;nBits+=eLen;for(;nBits>0;e=e*256+buffer[offset+i],i+=d,nBits-=8){}m=e&(1<<-nBits)-1;e>>=-nBits;nBits+=mLen;for(;nBits>0;m=m*256+buffer[offset+i],i+=d,nBits-=8){}if(e===0){e=1-eBias}else if(e===eMax){return m?NaN:(s?-1:1)*Infinity}else{m=m+Math.pow(2,mLen);e=e-eBias}return(s?-1:1)*m*Math.pow(2,e-mLen)};exports.write=function(buffer,value,offset,isLE,mLen,nBytes){var e,m,c;var eLen=nBytes*8-mLen-1;var eMax=(1<>1;var rt=mLen===23?Math.pow(2,-24)-Math.pow(2,-77):0;var i=isLE?0:nBytes-1;var d=isLE?1:-1;var s=value<0||value===0&&1/value<0?1:0;value=Math.abs(value);if(isNaN(value)||value===Infinity){m=isNaN(value)?1:0;e=eMax}else{e=Math.floor(Math.log(value)/Math.LN2);if(value*(c=Math.pow(2,-e))<1){e--;c*=2}if(e+eBias>=1){value+=rt/c}else{value+=rt*Math.pow(2,1-eBias)}if(value*c>=2){e++;c/=2}if(e+eBias>=eMax){m=0;e=eMax}else if(e+eBias>=1){m=(value*c-1)*Math.pow(2,mLen);e=e+eBias}else{m=value*Math.pow(2,eBias-1)*Math.pow(2,mLen);e=0}}for(;mLen>=8;buffer[offset+i]=m&255,i+=d,m/=256,mLen-=8){}e=e<0;buffer[offset+i]=e&255,i+=d,e/=256,eLen-=8){}buffer[offset+i-d]|=s*128}},{}],9:[function(require,module,exports){"use strict";function isUtf8(buf){if(!buf){return false}let i=0;const len=buf.length;while(i=194&&buf[i]<=223){if(buf[i+1]>>6===2){i+=2;continue}else{return false}}if((buf[i]===224&&buf[i+1]>=160&&buf[i+1]<=191||buf[i]===237&&buf[i+1]>=128&&buf[i+1]<=159)&&buf[i+2]>>6===2){i+=3;continue}if((buf[i]>=225&&buf[i]<=236||buf[i]>=238&&buf[i]<=239)&&buf[i+1]>>6===2&&buf[i+2]>>6===2){i+=3;continue}if((buf[i]===240&&buf[i+1]>=144&&buf[i+1]<=191||buf[i]>=241&&buf[i]<=243&&buf[i+1]>>6===2||buf[i]===244&&buf[i+1]>=128&&buf[i+1]<=143)&&buf[i+2]>>6===2&&buf[i+3]>>6===2){i+=4;continue}return false}return true}module.exports=isUtf8},{}],10:[function(require,module,exports){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(target,props){for(var i=0;iarr.length)len=arr.length;for(var i=0,arr2=new Array(len);i=to){return[]}return new Array(to-from).fill().map(function(_,i){return i+from})}},{key:"hexToInt",value:function hexToInt(hexString){if(hexString===undefined||hexString===null){return hexString}return Number.parseInt(hexString,16)}},{key:"intToHex",value:function intToHex(_int){if(_int===undefined||_int===null){return _int}var hexString=_int.toString(16);return"0x"+hexString}},{key:"messageToBuffer",value:function messageToBuffer(message){var buffer=_buffer.Buffer.from([]);try{if(typeof message==="string"){buffer=_buffer.Buffer.from(message.replace("0x",""),"hex")}else{buffer=_buffer.Buffer.from(message)}}catch(err){console.log("messageToBuffer error: ".concat(err))}return buffer}},{key:"bufferToHex",value:function bufferToHex(buf){return"0x"+_buffer.Buffer.from(buf).toString("hex")}}]);return Utils}();module.exports=Utils},{buffer:6}]},{},[4]); diff --git a/Safari Shared/SafariWebExtensionHandler.swift b/Safari Shared/SafariWebExtensionHandler.swift index 98dadfa7..0de46c23 100644 --- a/Safari Shared/SafariWebExtensionHandler.swift +++ b/Safari Shared/SafariWebExtensionHandler.swift @@ -39,8 +39,9 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { self.context = context if case let .ethereum(ethereumRequest) = request.body, ethereumRequest.method == .switchEthereumChain || ethereumRequest.method == .addEthereumChain { - if let chain = ethereumRequest.switchToChain { - let responseBody = ResponseToExtension.Ethereum(results: [ethereumRequest.address], chainId: chain.hexStringId, rpcURL: chain.nodeURLString) + if let switchToChainId = ethereumRequest.switchToChainId, let rpcURL = Nodes.getNode(chainId: switchToChainId) { + let chainId = String.hex(switchToChainId, withPrefix: true) + let responseBody = ResponseToExtension.Ethereum(results: [ethereumRequest.address], chainId: chainId, rpcURL: rpcURL) let response = ResponseToExtension(for: request, body: .ethereum(responseBody)) respond(with: response.json) } else { diff --git a/Safari Shared/web3-provider/ethereum.js b/Safari Shared/web3-provider/ethereum.js index 35657084..8c246f5b 100644 --- a/Safari Shared/web3-provider/ethereum.js +++ b/Safari Shared/web3-provider/ethereum.js @@ -22,7 +22,7 @@ class TokenaryEthereum extends EventEmitter { constructor() { super(); - const config = {address: "", chainId: "0x1", rpcUrl: "https://mainnet.infura.io/v3/3f99b6096fda424bbb26e17866dcddfc"}; + const config = {address: "", chainId: "0x1", rpcUrl: "https://eth.llamarpc.com"}; this.setConfig(config); this.idMapping = new IdMapping(); this.callbacks = new Map(); @@ -381,7 +381,7 @@ class TokenaryEthereum extends EventEmitter { let object = { object: data, address: this.address, - networkId: this.net_version() + chainId: this.chainId }; window.tokenary.postMessage(handler, id, object, "ethereum"); } else { diff --git a/Safari iOS/Resources/manifest.json b/Safari iOS/Resources/manifest.json index 5a0642cf..3e1119c2 100644 --- a/Safari iOS/Resources/manifest.json +++ b/Safari iOS/Resources/manifest.json @@ -4,7 +4,7 @@ "name": "__MSG_extension_name__", "description": "__MSG_extension_description__", - "version": "2.0.19", + "version": "2.0.20", "icons": { "48": "images/icon-48.png", @@ -40,6 +40,7 @@ "nativeMessaging", "browserAction", "storage", + "https://*.llamarpc.com/", "https://*.infura.io/", "https://*.infura.io/*", "https://*.infura.io/*/*", diff --git a/Safari macOS/Resources/manifest.json b/Safari macOS/Resources/manifest.json index 5a255719..7c3b70f5 100644 --- a/Safari macOS/Resources/manifest.json +++ b/Safari macOS/Resources/manifest.json @@ -4,7 +4,7 @@ "name": "__MSG_extension_name__", "description": "__MSG_extension_description__", - "version": "2.0.19", + "version": "2.0.20", "icons": { "48": "images/icon-48.png", @@ -38,6 +38,7 @@ "permissions": [ "nativeMessaging", "storage", + "https://*.llamarpc.com/", "https://*.infura.io/", "https://*.infura.io/*", "https://*.infura.io/*/*", diff --git a/Shared/Ethereum/Ethereum.swift b/Shared/Ethereum/Ethereum.swift index 7486b8aa..a0c9f198 100644 --- a/Shared/Ethereum/Ethereum.swift +++ b/Shared/Ethereum/Ethereum.swift @@ -96,7 +96,7 @@ struct Ethereum { let gasPriceHex = transaction.gasPrice?.cleanEvenHex, let gasHex = transaction.gas?.cleanEvenHex, let valueHex = transaction.value?.cleanEvenHex, - let chainID = Data(hexString: network.hexStringId.cleanEvenHex), + let chainID = Data(hexString: network.chainIdHexString.cleanEvenHex), let nonce = Data(hexString: nonceHex), let gasPrice = Data(hexString: gasPriceHex), let gasLimit = Data(hexString: gasHex), diff --git a/Shared/Ethereum/EthereumNetwork.swift b/Shared/Ethereum/EthereumNetwork.swift index 2f7497cf..d7f0238b 100644 --- a/Shared/Ethereum/EthereumNetwork.swift +++ b/Shared/Ethereum/EthereumNetwork.swift @@ -2,154 +2,19 @@ import Foundation -enum EthereumNetwork: Int { - case ethereum = 1 - case arbitrum = 42161 - case polygon = 137 - case optimism = 10 - case binance = 56 - case avalanche = 43114 - case gnosisChain = 100 - case fantomOpera = 250 - case celo = 42220 - case aurora = 1313161554 - case neon = 245022934 - case base = 8453 - case zora = 7777777 - case klaytn = 8217 - case scroll = 534352 +struct EthereumNetwork: Codable, Equatable { - // Testnets - case arbitrumRinkeby = 421611 - case arbitrumKovan = 144545313136048 - case optimisticKovan = 69 - case ethereumGoerli = 5 - case polygonMumbai = 80001 - case binanceTestnet = 97 - case avalancheFuji = 43113 - case fantomTestnet = 4002 - case fantomSonicOpen = 64240 - case neonDevnet = 245022926 - case scrollSepolia = 534351 + let chainId: Int + let name: String + let symbol: String + let nodeURLString: String + let isTestnet: Bool + let mightShowPrice: Bool - var id: Int { - return rawValue - } + var symbolIsETH: Bool { return symbol == "ETH" } + var chainIdHexString: String { String.hex(chainId, withPrefix: true) } + var isEthMainnet: Bool { return chainId == EthereumNetwork.ethMainnetChainId } - var hexStringId: String { - return String.hex(id, withPrefix: true) - } - - static func withChainId(_ chainId: String?) -> EthereumNetwork? { - guard let chainId = chainId else { return nil } - if let rawValue = Int(hexString: chainId) { - return EthereumNetwork(rawValue: rawValue) - } else { - return nil - } - } - - static let allMainnets: [EthereumNetwork] = [.ethereum, .zora, .base, .klaytn, .polygon, .optimism, .binance, .arbitrum, .avalanche, .gnosisChain, .fantomOpera, .celo, .aurora, .neon, .scroll] - static let allTestnets: [EthereumNetwork] = [.ethereumGoerli, .optimisticKovan, .arbitrumKovan, .arbitrumRinkeby, .polygonMumbai, .binanceTestnet, .avalancheFuji, .fantomTestnet, .neonDevnet, .fantomSonicOpen, .scrollSepolia] - - var name: String { - switch self { - case .ethereum: return "Ethereum" - case .zora: return "Zora" - case .klaytn: return "Klaytn" - case .base: return "Base" - case .arbitrum: return "Arbitrum" - case .optimism: return "Optimism" - case .polygon: return "Polygon" - case .binance: return "BNB Smart Chain" - case .avalanche: return "Avalanche" - case .gnosisChain: return "Gnosis Chain" - case .fantomOpera: return "Fantom Opera" - case .celo: return "Celo" - case .aurora: return "Aurora" - case .neon: return "Neon" - case .scroll: return "Scroll" - - case .arbitrumRinkeby: return "Arbitrum Rinkeby" - case .optimisticKovan: return "Optimistic Kovan" - case .ethereumGoerli: return "Ethereum Görli" - case .polygonMumbai: return "Polygon Mumbai" - case .arbitrumKovan: return "Arbitrum Kovan" - case .binanceTestnet: return "BNB Testnet" - case .avalancheFuji: return "Avalanche FUJI" - case .fantomTestnet: return "Fantom Testnet" - case .neonDevnet: return "Neon Devnet" - case .fantomSonicOpen: return "Fantom Sonic Open" - case .scrollSepolia: return "Scroll Sepolia" - } - } - - var symbol: String { - switch self { - case .binance, .binanceTestnet: - return "BNB" - case .polygon, .polygonMumbai: - return "MATIC" - case .arbitrum, .arbitrumKovan, .arbitrumRinkeby, .ethereum, .ethereumGoerli, .optimism, .optimisticKovan, .aurora, .zora, .base, .scroll, .scrollSepolia: - return "ETH" - case .avalanche, .avalancheFuji: - return "AVAX" - case .gnosisChain: - return "xDai" - case .fantomOpera, .fantomTestnet, .fantomSonicOpen: - return "FTM" - case .celo: - return "CELO" - case .neonDevnet, .neon: - return "NEON" - case .klaytn: - return "KLAY" - } - } - - var symbolIsETH: Bool { - return symbol == "ETH" - } - - var hasUSDPrice: Bool { - switch self { - case .ethereum, .arbitrum, .klaytn, .polygon, .optimism, .binance, .avalanche, .gnosisChain, .fantomOpera, .celo, .aurora, .neon, .base, .zora, .scroll: - return symbolIsETH - case .fantomTestnet, .neonDevnet, .avalancheFuji, .binanceTestnet, .polygonMumbai, .ethereumGoerli, .optimisticKovan, .arbitrumKovan, .arbitrumRinkeby, .fantomSonicOpen, .scrollSepolia: - return false - } - } - - var nodeURLString: String { - switch self { - case .ethereum: return "https://mainnet.infura.io/v3/" + infuraKey - case .arbitrum: return "https://arbitrum-mainnet.infura.io/v3/" + infuraKey - case .optimism: return "https://optimism-mainnet.infura.io/v3/" + infuraKey - case .polygon: return "https://polygon-mainnet.infura.io/v3/" + infuraKey - case .binance: return "https://bsc-dataseed.binance.org/" - case .avalanche: return "https://api.avax.network/ext/bc/C/rpc" - case .gnosisChain: return "https://rpc.gnosischain.com/" - case .fantomOpera: return "https://rpc.ftm.tools/" - case .celo: return "https://rpc.ankr.com/celo" - case .aurora: return "https://mainnet.aurora.dev" - case .neon: return "https://neon-proxy-mainnet.solana.p2p.org/" - case .zora: return "https://rpc.zora.energy" - case .base: return "https://mainnet.base.org" - case .klaytn: return "https://1rpc.io/klay" - case .scroll: return "https://rpc.scroll.io" - - case .arbitrumRinkeby: return "https://rinkeby.arbitrum.io/rpc" - case .arbitrumKovan: return "https://kovan5.arbitrum.io/rpc" - case .optimisticKovan: return "https://kovan.optimism.io" - case .ethereumGoerli: return "https://rpc.ankr.com/eth_goerli" - case .binanceTestnet: return "https://data-seed-prebsc-1-s1.binance.org:8545/" - case .avalancheFuji: return "https://api.avax-test.network/ext/bc/C/rpc" - case .polygonMumbai: return "https://rpc.ankr.com/polygon_mumbai" - case .fantomTestnet: return "https://rpc.testnet.fantom.network/" - case .neonDevnet: return "https://devnet.neonevm.org/" - case .fantomSonicOpen: return "https://rpcapi.sonic.fantom.network/" - case .scrollSepolia: return "https://sepolia-rpc.scroll.io" - } - } + static let ethMainnetChainId = 1 } diff --git a/Shared/Ethereum/Networks.swift b/Shared/Ethereum/Networks.swift new file mode 100644 index 00000000..f203003b --- /dev/null +++ b/Shared/Ethereum/Networks.swift @@ -0,0 +1,54 @@ +// Copyright © 2023 Tokenary. All rights reserved. + +import Foundation + +struct Networks { + + static var ethereum: EthereumNetwork { + return withChainId(EthereumNetwork.ethMainnetChainId)! + } + + static func withChainId(_ chainId: Int?) -> EthereumNetwork? { + guard let chainId = chainId else { return nil } + return allBundledDict[chainId] + } + + static func withChainIdHex(_ chainIdHex: String?) -> EthereumNetwork? { + guard let chainIdHex = chainIdHex, let id = Int(hexString: chainIdHex) else { return nil } + return allBundledDict[id] + } + + static let allMainnets: [EthereumNetwork] = { + return allBundled.filter { !$0.isTestnet } + }() + + static let allTestnets: [EthereumNetwork] = { + return allBundled.filter { $0.isTestnet } + }() + + private static let allBundled: [EthereumNetwork] = { + return Array(allBundledDict.values.sorted(by: { $0.name < $1.name })) + }() + + private static let allBundledDict: [Int: EthereumNetwork] = { + if let url = Bundle.main.url(forResource: "bundled-networks", withExtension: "json"), + let data = try? Data(contentsOf: url), + let bundledNetworks = try? JSONDecoder().decode([Int: BundledNetwork].self, from: data) { + let mapped = bundledNetworks.compactMap { (key, value) -> (Int, EthereumNetwork)? in + guard let node = Nodes.getNode(chainId: key) else { return nil } + let network = EthereumNetwork(chainId: key, + name: value.name, + symbol: value.symbol, + nodeURLString: node, + isTestnet: value.isTest, + mightShowPrice: value.okToShowPriceForSymbol) + return (key, network) + } + let dict = [Int: EthereumNetwork](uniqueKeysWithValues: mapped) + return dict + } else { + return [:] + } + }() + +} diff --git a/Shared/Ethereum/Nodes.swift b/Shared/Ethereum/Nodes.swift new file mode 100644 index 00000000..dec50e0d --- /dev/null +++ b/Shared/Ethereum/Nodes.swift @@ -0,0 +1,20 @@ +// Copyright © 2023 Tokenary. All rights reserved. + +import Foundation + +struct Nodes { + + static func getNode(chainId: Int) -> String? { + if let domain = BundledNodes.dict[chainId] { + let https = "https://" + domain + if domain.hasSuffix(".infura.io/v3/") { + return https + infuraKey + } else { + return https + } + } else { + return nil + } + } + +} diff --git a/Shared/Ethereum/Transaction.swift b/Shared/Ethereum/Transaction.swift index 3ca69379..83f966e4 100644 --- a/Shared/Ethereum/Transaction.swift +++ b/Shared/Ethereum/Transaction.swift @@ -21,12 +21,12 @@ struct Transaction { return value.gweiUInt } - func description(chain: EthereumNetwork, ethPrice: Double?) -> String { + func description(chain: EthereumNetwork, price: Double?) -> String { var result = ["🌐 " + chain.name] - if let value = valueWithSymbol(chain: chain, ethPrice: ethPrice, withLabel: false) { + if let value = valueWithSymbol(chain: chain, price: price, withLabel: false) { result.append(value) } - result.append(feeWithSymbol(chain: chain, ethPrice: ethPrice)) + result.append(feeWithSymbol(chain: chain, price: price)) result.append(dataWithLabel) return result.joined(separator: "\n\n") @@ -54,13 +54,13 @@ struct Transaction { return "Gas price: " + gwei } - func feeWithSymbol(chain: EthereumNetwork, ethPrice: Double?) -> String { + func feeWithSymbol(chain: EthereumNetwork, price: Double?) -> String { let feeString: String if let gasPriceString = gasPrice, let gasString = gas, let gasPrice = BigInt(hexString: gasPriceString), let gas = BigInt(hexString: gasString) { let fee = gas * gasPrice - let costString = chain.hasUSDPrice ? cost(value: fee, price: ethPrice) : "" + let costString = chain.mightShowPrice ? cost(value: fee, price: price) : "" feeString = fee.eth.prefix(8) + " \(chain.symbol)" + costString } else { feeString = Strings.calculating @@ -68,9 +68,9 @@ struct Transaction { return "Fee: " + feeString } - func valueWithSymbol(chain: EthereumNetwork, ethPrice: Double?, withLabel: Bool) -> String? { + func valueWithSymbol(chain: EthereumNetwork, price: Double?, withLabel: Bool) -> String? { guard let value = value, let value = BigInt(hexString: value) else { return nil } - let costString = chain.hasUSDPrice ? cost(value: value, price: ethPrice) : "" + let costString = chain.mightShowPrice ? cost(value: value, price: price) : "" let valueString = "\(value.eth) \(chain.symbol)" + costString return withLabel ? "Value: " + valueString : valueString } diff --git a/Shared/Services/DappRequestProcessor.swift b/Shared/Services/DappRequestProcessor.swift index 8ef3d45b..ba047955 100644 --- a/Shared/Services/DappRequestProcessor.swift +++ b/Shared/Services/DappRequestProcessor.swift @@ -27,7 +27,8 @@ struct DappRequestProcessor { guard let coin = CoinType.correspondingToInpageProvider(configuration.provider) else { return nil } return walletsManager.getSpecificAccount(coin: coin, address: configuration.address) } - let network = body.providerConfigurations.compactMap { $0.network }.first + let chainId = body.providerConfigurations.compactMap { $0.chainId }.first + let network = Networks.withChainIdHex(chainId) let initiallyConnectedProviders = Set(body.providerConfigurations.map { $0.provider }) let action = SelectAccountAction(peer: request.peerMeta, coinType: nil, @@ -41,7 +42,9 @@ struct DappRequestProcessor { let account = specificWalletAccount.account switch account.coin { case .ethereum: - let responseBody = ResponseToExtension.Ethereum(results: [account.address], chainId: chain.hexStringId, rpcURL: chain.nodeURLString) + let responseBody = ResponseToExtension.Ethereum(results: [account.address], + chainId: chain.chainIdHexString, + rpcURL: chain.nodeURLString) specificProviderBodies.append(.ethereum(responseBody)) default: fatalError("Can't select that coin") @@ -82,7 +85,7 @@ struct DappRequestProcessor { network: nil, source: .safariExtension) { chain, specificWalletAccounts in if let chain = chain, let specificWalletAccount = specificWalletAccounts?.first, specificWalletAccount.account.coin == .ethereum { - let responseBody = ResponseToExtension.Ethereum(results: [specificWalletAccount.account.address], chainId: chain.hexStringId, rpcURL: chain.nodeURLString) + let responseBody = ResponseToExtension.Ethereum(results: [specificWalletAccount.account.address], chainId: chain.chainIdHexString, rpcURL: chain.nodeURLString) respond(to: request, body: .ethereum(responseBody), completion: completion) } else { respond(to: request, error: Strings.canceled, completion: completion) @@ -137,7 +140,8 @@ struct DappRequestProcessor { } case .signTransaction: if let transaction = ethereumRequest.transaction, - let chain = ethereumRequest.chain, + let chainId = ethereumRequest.currentChainId, + let chain = Networks.withChainId(chainId), let account = account, let privateKey = privateKey { let action = SendTransactionAction(provider: request.provider, diff --git a/Shared/Services/PriceService.swift b/Shared/Services/PriceService.swift index fd6580e9..ec1acc37 100644 --- a/Shared/Services/PriceService.swift +++ b/Shared/Services/PriceService.swift @@ -4,8 +4,22 @@ import Foundation class PriceService { - private struct PriceResponse: Codable { - let ethereum: Price + private struct Prices: Codable { + + let eth: Price? + let bnb: Price? + let matic: Price? + let ftm: Price? + let avax: Price? + + enum CodingKeys: String, CodingKey, CaseIterable { + case eth = "ethereum" + case bnb = "binancecoin" + case matic = "matic-network" + case ftm = "fantom" + case avax = "avalanche-2" + } + } private struct Price: Codable { @@ -15,10 +29,14 @@ class PriceService { static let shared = PriceService() private let jsonDecoder = JSONDecoder() private let urlSession = URLSession(configuration: .ephemeral) + private let idsQuery: String = { + let ids = Prices.CodingKeys.allCases.map { $0.rawValue } + return ids.joined(separator: "%2C") + }() private init() {} - var currentPrice: Double? + private var currentPrices: Prices? func start() { getPrice(scheduleNextRequest: true) @@ -28,13 +46,31 @@ class PriceService { getPrice(scheduleNextRequest: false) } + func forNetwork(_ network: EthereumNetwork) -> Double? { + guard network.mightShowPrice else { return nil } + switch network.symbol { + case "ETH": + return currentPrices?.eth?.usd + case "BNB": + return currentPrices?.bnb?.usd + case "FTM": + return currentPrices?.ftm?.usd + case "MATIC": + return currentPrices?.matic?.usd + case "AVAX": + return currentPrices?.avax?.usd + default: + return nil + } + } + private func getPrice(scheduleNextRequest: Bool) { - let url = URL(string: "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd")! + let url = URL(string: "https://api.coingecko.com/api/v3/simple/price?ids=\(idsQuery)&vs_currencies=usd")! let dataTask = urlSession.dataTask(with: url) { [weak self] (data, _, _) in if let data = data, - let priceResponse = try? self?.jsonDecoder.decode(PriceResponse.self, from: data) { + let pricesResponse = try? self?.jsonDecoder.decode(Prices.self, from: data) { DispatchQueue.main.async { - self?.currentPrice = priceResponse.ethereum.usd + self?.currentPrices = pricesResponse } } if scheduleNextRequest { diff --git a/Shared/Views/NetworksListView.swift b/Shared/Views/NetworksListView.swift new file mode 100644 index 00000000..abe6df4f --- /dev/null +++ b/Shared/Views/NetworksListView.swift @@ -0,0 +1,96 @@ +// Copyright © 2023 Tokenary. All rights reserved. + +import SwiftUI + +struct NetworksListView: View { + @State private var searchText: String = "" + let items: [String] = Networks.all().map { $0.name } + + @Environment(\.presentationMode) var presentationMode + + var filteredItems: [String] { + items.filter { $0.contains(searchText) || searchText.isEmpty } + } + + var body: some View { + VStack { + SearchBar(text: $searchText) + List(filteredItems, id: \.self) { item in + Text(item) + } + + Divider() // Separate the list from the buttons + + HStack { + Spacer() + Button("Cancel") { + self.presentationMode.wrappedValue.dismiss() + } + .padding() + + Button("OK") { + self.presentationMode.wrappedValue.dismiss() + } + .padding() + } + } + } +} + +struct SearchBar: View { + @Binding var text: String + + var body: some View { + HStack { + TextField("Search ...", text: $text) + .textFieldStyle(RoundedBorderTextFieldStyle()) + }.padding() + } +} + +#if os(iOS) +import UIKit + +extension UIViewController { + func showPopup() { + let contentView = NetworksListView() + let hostingController = UIHostingController(rootView: contentView) + hostingController.modalPresentationStyle = .fullScreen + self.present(hostingController, animated: true, completion: nil) + } +} + +#elseif os(macOS) +import Cocoa + +var popupWindow: NSWindow? // keep a reference within a NSViewController + +extension NSViewController { + + func showPopup() { + let contentView = NetworksListView() + + popupWindow = NSWindow( + contentRect: NSRect(x: 0, y: 0, width: 300, height: 400), + styleMask: [.closable, .fullSizeContentView, .titled], + backing: .buffered, defer: false) + popupWindow?.center() + popupWindow?.titleVisibility = .hidden + popupWindow?.titlebarAppearsTransparent = true + popupWindow?.isMovableByWindowBackground = true + popupWindow?.backgroundColor = NSColor.windowBackgroundColor + popupWindow?.isOpaque = false + popupWindow?.hasShadow = true + + popupWindow?.contentView?.wantsLayer = true + popupWindow?.contentView?.layer?.cornerRadius = 10 + popupWindow?.contentView?.layer?.masksToBounds = true + + popupWindow?.isReleasedWhenClosed = false + popupWindow?.contentView = NSHostingView(rootView: contentView) + popupWindow?.makeKeyAndOrderFront(nil) + } + +} + +#endif diff --git a/Tokenary iOS/Screens/Accounts/AccountsListViewController.swift b/Tokenary iOS/Screens/Accounts/AccountsListViewController.swift index ea692ce0..8ffc6263 100644 --- a/Tokenary iOS/Screens/Accounts/AccountsListViewController.swift +++ b/Tokenary iOS/Screens/Accounts/AccountsListViewController.swift @@ -27,7 +27,7 @@ class AccountsListViewController: UIViewController, DataStateContainer { private var sections = [Section]() private let walletsManager = WalletsManager.shared - private var network = EthereumNetwork.ethereum + private var network = Networks.ethereum var selectAccountAction: SelectAccountAction? private var wallets: [TokenaryWallet] { @@ -302,7 +302,7 @@ class AccountsListViewController: UIViewController, DataStateContainer { let actionSheet = UIAlertController(title: Strings.selectNetwork, message: nil, preferredStyle: .actionSheet) actionSheet.popoverPresentationController?.sourceView = networkButton - for network in EthereumNetwork.allMainnets { + for network in Networks.allMainnets { let prefix = network == self.network ? "✅ " : "" let action = UIAlertAction(title: prefix + network.name, style: .default) { [weak self] _ in self?.selectNetwork(network) @@ -321,7 +321,7 @@ class AccountsListViewController: UIViewController, DataStateContainer { private func showTestnets() { let actionSheet = UIAlertController(title: Strings.selectTestnet, message: nil, preferredStyle: .actionSheet) actionSheet.popoverPresentationController?.sourceView = networkButton - for network in EthereumNetwork.allTestnets { + for network in Networks.allTestnets { let prefix = network == self.network ? "✅ " : "" let action = UIAlertAction(title: prefix + network.name, style: .default) { [weak self] _ in self?.selectNetwork(network) diff --git a/Tokenary iOS/Screens/Approve/ApproveTransactionViewController.swift b/Tokenary iOS/Screens/Approve/ApproveTransactionViewController.swift index 92e7b755..37896187 100644 --- a/Tokenary iOS/Screens/Approve/ApproveTransactionViewController.swift +++ b/Tokenary iOS/Screens/Approve/ApproveTransactionViewController.swift @@ -59,7 +59,7 @@ class ApproveTransactionViewController: UIViewController { navigationItem.largeTitleDisplayMode = .always isModalInPresentation = true - if chain == .ethereum { + if chain.isEthMainnet { sectionModels = [[], [.gasPriceSlider]] } else { sectionModels = [[]] @@ -85,10 +85,11 @@ class ApproveTransactionViewController: UIViewController { .textWithImage(text: chain.name, imageURL: nil, image: Images.network) ] - if let value = transaction.valueWithSymbol(chain: chain, ethPrice: priceService.currentPrice, withLabel: true) { + let price = priceService.forNetwork(chain) + if let value = transaction.valueWithSymbol(chain: chain, price: price, withLabel: true) { cellModels.append(.text(text: value, oneLine: false)) } - cellModels.append(.text(text: transaction.feeWithSymbol(chain: chain, ethPrice: priceService.currentPrice), oneLine: false)) + cellModels.append(.text(text: transaction.feeWithSymbol(chain: chain, price: price), oneLine: false)) cellModels.append(.text(text: transaction.gasPriceWithLabel(chain: chain), oneLine: false)) if let data = transaction.nonEmptyDataWithLabel { cellModels.append(.text(text: data, oneLine: true)) diff --git a/Tokenary macOS/Screens/AccountsListViewController.swift b/Tokenary macOS/Screens/AccountsListViewController.swift index 1ddb204c..6703835c 100644 --- a/Tokenary macOS/Screens/AccountsListViewController.swift +++ b/Tokenary macOS/Screens/AccountsListViewController.swift @@ -127,7 +127,7 @@ class AccountsListViewController: NSViewController { private func callCompletion(specificWalletAccounts: [SpecificWalletAccount]?) { if !didCallCompletion { didCallCompletion = true - let network = selectAccountAction?.network ?? .ethereum + let network = selectAccountAction?.network ?? Networks.ethereum selectAccountAction?.completion(network, specificWalletAccounts) } } @@ -147,18 +147,18 @@ class AccountsListViewController: NSViewController { networkButton.isHidden = true } else if networkButton.menu == nil { let menu = NSMenu() - for mainnet in EthereumNetwork.allMainnets { + for mainnet in Networks.allMainnets { let item = NSMenuItem(title: mainnet.name, action: #selector(didSelectChain(_:)), keyEquivalent: "") - item.tag = mainnet.id + item.tag = mainnet.chainId menu.addItem(item) } let submenuItem = NSMenuItem() submenuItem.title = Strings.testnets let submenu = NSMenu() - for testnet in EthereumNetwork.allTestnets { + for testnet in Networks.allTestnets { let item = NSMenuItem(title: testnet.name, action: #selector(didSelectChain(_:)), keyEquivalent: "") - item.tag = testnet.id + item.tag = testnet.chainId submenu.addItem(item) } @@ -171,7 +171,7 @@ class AccountsListViewController: NSViewController { let titleItem = NSMenuItem(title: Strings.selectNetworkOptionally, action: nil, keyEquivalent: "") menu.addItem(titleItem) - if let network = selectAccountAction.network, network != .ethereum { + if let network = selectAccountAction.network, !network.isEthMainnet { selectNetwork(network) } } @@ -259,7 +259,7 @@ class AccountsListViewController: NSViewController { @objc private func didSelectChain(_ sender: AnyObject) { guard let menuItem = sender as? NSMenuItem, - let selectedNetwork = EthereumNetwork(rawValue: menuItem.tag) else { return } + let selectedNetwork = Networks.withChainId(menuItem.tag) else { return } selectNetwork(selectedNetwork) } diff --git a/Tokenary macOS/Screens/ApproveTransactionViewController.swift b/Tokenary macOS/Screens/ApproveTransactionViewController.swift index bda9a059..4525ea44 100644 --- a/Tokenary macOS/Screens/ApproveTransactionViewController.swift +++ b/Tokenary macOS/Screens/ApproveTransactionViewController.swift @@ -85,7 +85,7 @@ class ApproveTransactionViewController: NSViewController { } private func updateInterface() { - if chain != .ethereum { + if !chain.isEthMainnet { speedContainerStackView.isHidden = true gweiLabel.isHidden = true infoTextViewBottomConstraint.constant = 30 @@ -94,7 +94,7 @@ class ApproveTransactionViewController: NSViewController { okButton.isEnabled = transaction.hasFee enableSpeedConfigurationIfNeeded() - let meta = transaction.description(chain: chain, ethPrice: priceService.currentPrice) + let meta = transaction.description(chain: chain, price: priceService.forNetwork(chain)) if metaTextView.string != meta { metaTextView.string = meta } diff --git a/Tokenary.xcodeproj/project.pbxproj b/Tokenary.xcodeproj/project.pbxproj index c0e99fba..7a911d63 100644 --- a/Tokenary.xcodeproj/project.pbxproj +++ b/Tokenary.xcodeproj/project.pbxproj @@ -140,6 +140,9 @@ 2C96D3A62763CCA000687301 /* Images.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D3A52763CCA000687301 /* Images.swift */; }; 2C96D3A92763D13400687301 /* DataStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D3A72763D13400687301 /* DataStateView.swift */; }; 2C96D3AA2763D13400687301 /* DataStateView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2C96D3A82763D13400687301 /* DataStateView.xib */; }; + 2C9B55D12AF2AE4B008BE899 /* BundledNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9B55D02AF2AE4B008BE899 /* BundledNetwork.swift */; }; + 2C9B55D22AF2AE4B008BE899 /* BundledNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9B55D02AF2AE4B008BE899 /* BundledNetwork.swift */; }; + 2C9B55D32AF2AE4B008BE899 /* BundledNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9B55D02AF2AE4B008BE899 /* BundledNetwork.swift */; }; 2C9F0B6826BDCB2E008FA3D6 /* EthereumNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9F0B6726BDCB2E008FA3D6 /* EthereumNetwork.swift */; }; 2CAA412526C7CD93009F3535 /* ReviewRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CAA412426C7CD93009F3535 /* ReviewRequester.swift */; }; 2CB3845A27654EA900A189B9 /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 2CB3845827654E9700A189B9 /* _locales */; }; @@ -180,6 +183,21 @@ 2CE0594527640EF10042D844 /* ResponseToExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C773F61274523DC007B04E7 /* ResponseToExtension.swift */; }; 2CE0594627640F470042D844 /* UserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC89470269A334A00879245 /* UserDefaults.swift */; }; 2CE3D012267F73C00032A62E /* Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CE3D011267F73C00032A62E /* Transaction.swift */; }; + 2CED86A52AF00BC9006F9E26 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86A42AF00BC9006F9E26 /* main.swift */; }; + 2CED86B02AF0167F006F9E26 /* EIP155ChainData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86AF2AF0167F006F9E26 /* EIP155ChainData.swift */; }; + 2CED86B32AF01F99006F9E26 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C603D0126B6E13F00956955 /* String.swift */; }; + 2CED86B62AF17D5A006F9E26 /* BundledNodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B52AF17D5A006F9E26 /* BundledNodes.swift */; }; + 2CED86B72AF17D5A006F9E26 /* BundledNodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B52AF17D5A006F9E26 /* BundledNodes.swift */; }; + 2CED86BA2AF1820E006F9E26 /* Nodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B92AF1820E006F9E26 /* Nodes.swift */; }; + 2CED86BB2AF1820E006F9E26 /* Nodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B92AF1820E006F9E26 /* Nodes.swift */; }; + 2CED86BF2AF25C32006F9E26 /* Networks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86BE2AF25C32006F9E26 /* Networks.swift */; }; + 2CED86C02AF25C32006F9E26 /* Networks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86BE2AF25C32006F9E26 /* Networks.swift */; }; + 2CED86C12AF26114006F9E26 /* bundled-networks.json in Resources */ = {isa = PBXBuildFile; fileRef = 2CED86A92AF00F56006F9E26 /* bundled-networks.json */; }; + 2CED86C22AF2611D006F9E26 /* bundled-networks.json in Resources */ = {isa = PBXBuildFile; fileRef = 2CED86A92AF00F56006F9E26 /* bundled-networks.json */; }; + 2CED86C32AF262E6006F9E26 /* Nodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B92AF1820E006F9E26 /* Nodes.swift */; }; + 2CED86C42AF262E7006F9E26 /* Nodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B92AF1820E006F9E26 /* Nodes.swift */; }; + 2CED86C52AF26327006F9E26 /* BundledNodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B52AF17D5A006F9E26 /* BundledNodes.swift */; }; + 2CED86C62AF26328006F9E26 /* BundledNodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B52AF17D5A006F9E26 /* BundledNodes.swift */; }; 2CEFEB16274D5DCA00CE23BD /* inpage.js in Resources */ = {isa = PBXBuildFile; fileRef = 2CEFEB15274D5DC900CE23BD /* inpage.js */; }; 2CF25597275A46D300AE54B9 /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C528A15267FA8EB00CA3ADD /* Defaults.swift */; }; 2CF25598275A46D600AE54B9 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C901C492689F01700D0926A /* Strings.swift */; }; @@ -355,6 +373,9 @@ 2C96D3A52763CCA000687301 /* Images.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Images.swift; sourceTree = ""; }; 2C96D3A72763D13400687301 /* DataStateView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataStateView.swift; sourceTree = ""; }; 2C96D3A82763D13400687301 /* DataStateView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DataStateView.xib; sourceTree = ""; }; + 2C9931DB2AEEC0E200577C8A /* NetworksListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworksListView.swift; sourceTree = ""; }; + 2C9B55D02AF2AE4B008BE899 /* BundledNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundledNetwork.swift; sourceTree = ""; }; + 2C9B55D42AF2B004008BE899 /* nodes-to-bundle.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "nodes-to-bundle.json"; sourceTree = ""; }; 2C9F0B6726BDCB2E008FA3D6 /* EthereumNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumNetwork.swift; sourceTree = ""; }; 2CAA412426C7CD93009F3535 /* ReviewRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewRequester.swift; sourceTree = ""; }; 2CB3844327654BF600A189B9 /* error.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = error.js; path = "web3-provider/error.js"; sourceTree = ""; }; @@ -389,6 +410,13 @@ 2CE059482764169E0042D844 /* Tokenary iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Tokenary iOS.entitlements"; sourceTree = ""; }; 2CE0594B2764DF9A0042D844 /* Safari iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Safari iOS.entitlements"; sourceTree = ""; }; 2CE3D011267F73C00032A62E /* Transaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Transaction.swift; sourceTree = ""; }; + 2CED86A22AF00BC9006F9E26 /* tools */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tools; sourceTree = BUILT_PRODUCTS_DIR; }; + 2CED86A42AF00BC9006F9E26 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; + 2CED86A92AF00F56006F9E26 /* bundled-networks.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "bundled-networks.json"; sourceTree = ""; }; + 2CED86AF2AF0167F006F9E26 /* EIP155ChainData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EIP155ChainData.swift; sourceTree = ""; }; + 2CED86B52AF17D5A006F9E26 /* BundledNodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundledNodes.swift; sourceTree = ""; }; + 2CED86B92AF1820E006F9E26 /* Nodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Nodes.swift; sourceTree = ""; }; + 2CED86BE2AF25C32006F9E26 /* Networks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Networks.swift; sourceTree = ""; }; 2CEFEB15274D5DC900CE23BD /* inpage.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = inpage.js; sourceTree = ""; }; 2CF255B3275A744000AE54B9 /* PasswordViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordViewController.swift; sourceTree = ""; }; 2CF255B5275A746000AE54B9 /* AccountsListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsListViewController.swift; sourceTree = ""; }; @@ -435,6 +463,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 2CED869F2AF00BC9006F9E26 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -483,6 +518,7 @@ 2CCEB7A227592A3800768473 /* Safari Shared */, 2C09CBA0273979C1009AD39B /* Safari macOS */, 2CCEB82E27594E2A00768473 /* Safari iOS */, + 2CED86A32AF00BC9006F9E26 /* tools */, 2C19953D2674C4B900A8E370 /* Products */, FB5786212D81829B0FADBD25 /* Pods */, 2A7484A18D772B4233D171DA /* Frameworks */, @@ -496,6 +532,7 @@ 2C5FF96F26C84F7B00B32ACC /* Tokenary iOS.app */, 2C09CB9F273979C1009AD39B /* Safari macOS.appex */, 2CCEB82D27594E2A00768473 /* Safari iOS.appex */, + 2CED86A22AF00BC9006F9E26 /* tools */, ); name = Products; sourceTree = ""; @@ -627,9 +664,11 @@ isa = PBXGroup; children = ( 2C1995552674D0F300A8E370 /* Ethereum.swift */, + 2CE3D011267F73C00032A62E /* Transaction.swift */, 2C8944CA2AEB0C10006A711F /* EthereumRPC.swift */, 2C9F0B6726BDCB2E008FA3D6 /* EthereumNetwork.swift */, - 2CE3D011267F73C00032A62E /* Transaction.swift */, + 2CED86BE2AF25C32006F9E26 /* Networks.swift */, + 2CED86B92AF1820E006F9E26 /* Nodes.swift */, ); path = Ethereum; sourceTree = ""; @@ -705,6 +744,14 @@ path = Library; sourceTree = ""; }; + 2C9B55D52AF2B8D5008BE899 /* helpers */ = { + isa = PBXGroup; + children = ( + 2C9B55D42AF2B004008BE899 /* nodes-to-bundle.json */, + ); + path = helpers; + sourceTree = ""; + }; 2CB3844027654A0D00A189B9 /* Resources */ = { isa = PBXGroup; children = ( @@ -755,6 +802,7 @@ 2CF255A4275A483600AE54B9 /* Services */, 2CF2559F275A47B600AE54B9 /* Extension */, 2CD0668826B213BB00728C20 /* Wallets */, + 2CED86B12AF01DFD006F9E26 /* Views */, 2CF25596275A468B00AE54B9 /* Models */, 2C8944D02AEC34F2006A711F /* Utilities */, 2CF255AF275A490600AE54B9 /* Supporting Files */, @@ -808,6 +856,43 @@ path = Wallets; sourceTree = ""; }; + 2CED86A32AF00BC9006F9E26 /* tools */ = { + isa = PBXGroup; + children = ( + 2CED86A42AF00BC9006F9E26 /* main.swift */, + 2CED86B42AF17BF0006F9E26 /* bundled */, + 2CED86BD2AF225A4006F9E26 /* models */, + 2C9B55D52AF2B8D5008BE899 /* helpers */, + ); + path = tools; + sourceTree = ""; + }; + 2CED86B12AF01DFD006F9E26 /* Views */ = { + isa = PBXGroup; + children = ( + 2C9931DB2AEEC0E200577C8A /* NetworksListView.swift */, + ); + path = Views; + sourceTree = ""; + }; + 2CED86B42AF17BF0006F9E26 /* bundled */ = { + isa = PBXGroup; + children = ( + 2CED86A92AF00F56006F9E26 /* bundled-networks.json */, + 2CED86B52AF17D5A006F9E26 /* BundledNodes.swift */, + ); + path = bundled; + sourceTree = ""; + }; + 2CED86BD2AF225A4006F9E26 /* models */ = { + isa = PBXGroup; + children = ( + 2CED86AF2AF0167F006F9E26 /* EIP155ChainData.swift */, + 2C9B55D02AF2AE4B008BE899 /* BundledNetwork.swift */, + ); + path = models; + sourceTree = ""; + }; 2CF25596275A468B00AE54B9 /* Models */ = { isa = PBXGroup; children = ( @@ -962,13 +1047,29 @@ productReference = 2CCEB82D27594E2A00768473 /* Safari iOS.appex */; productType = "com.apple.product-type.app-extension"; }; + 2CED86A12AF00BC9006F9E26 /* tools */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2CED86A82AF00BC9006F9E26 /* Build configuration list for PBXNativeTarget "tools" */; + buildPhases = ( + 2CED869E2AF00BC9006F9E26 /* Sources */, + 2CED869F2AF00BC9006F9E26 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tools; + productName = tools; + productReference = 2CED86A22AF00BC9006F9E26 /* tools */; + productType = "com.apple.product-type.tool"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 2C1995342674C4B900A8E370 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1310; + LastSwiftUpdateCheck = 1500; LastUpgradeCheck = 1240; TargetAttributes = { 2C09CB9E273979C1009AD39B = { @@ -983,6 +1084,9 @@ 2CCEB82C27594E2A00768473 = { CreatedOnToolsVersion = 13.1; }; + 2CED86A12AF00BC9006F9E26 = { + CreatedOnToolsVersion = 15.0.1; + }; }; }; buildConfigurationList = 2C1995372674C4B900A8E370 /* Build configuration list for PBXProject "Tokenary" */; @@ -1002,6 +1106,7 @@ 2C5FF96E26C84F7B00B32ACC /* Tokenary iOS */, 2C09CB9E273979C1009AD39B /* Safari macOS */, 2CCEB82C27594E2A00768473 /* Safari iOS */, + 2CED86A12AF00BC9006F9E26 /* tools */, ); }; /* End PBXProject section */ @@ -1025,6 +1130,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2CED86C12AF26114006F9E26 /* bundled-networks.json in Resources */, 2C6B964F26B9D98C00D2C819 /* Colors.xcassets in Resources */, 2C1995442674C4BA00A8E370 /* Assets.xcassets in Resources */, 2C1995472674C4BA00A8E370 /* Main.storyboard in Resources */, @@ -1036,6 +1142,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2CED86C22AF2611D006F9E26 /* bundled-networks.json in Resources */, 2C96D3AA2763D13400687301 /* DataStateView.xib in Resources */, 2C5FF97E26C84F7C00B32ACC /* LaunchScreen.storyboard in Resources */, 2C40709527667A8600AB3D55 /* ImageWithLabelTableViewCell.xib in Resources */, @@ -1202,11 +1309,13 @@ 2C2AA1D728AFB1AD00E35DBF /* MultipleResponseToExtension.swift in Sources */, 2C773F5E27450B97007B04E7 /* ExtensionBridge.swift in Sources */, 2C264BDE27B5AC5400234393 /* EthereumResponseToExtension.swift in Sources */, + 2CED86BA2AF1820E006F9E26 /* Nodes.swift in Sources */, 2CC8C5AC276A7EF70083FB1B /* EthereumNetwork.swift in Sources */, 2C264BC327B2F2C100234393 /* EthereumSafariRequest.swift in Sources */, 2C264BBE27B2F25E00234393 /* SafariRequest.swift in Sources */, 2C09CBA2273979C1009AD39B /* SafariWebExtensionHandler.swift in Sources */, 2C773F63274523DC007B04E7 /* ResponseToExtension.swift in Sources */, + 2CED86B62AF17D5A006F9E26 /* BundledNodes.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1239,8 +1348,10 @@ 2C8A09E326757FC000993638 /* AccountCellView.swift in Sources */, 2C6B964C26B9D92500D2C819 /* NSColor.swift in Sources */, 2C603D0226B6E13F00956955 /* String.swift in Sources */, + 2CED86C32AF262E6006F9E26 /* Nodes.swift in Sources */, 2C264BC127B2F2C100234393 /* EthereumSafariRequest.swift in Sources */, 2C264BD027B2F30C00234393 /* UnknownSafariRequest.swift in Sources */, + 2CED86BF2AF25C32006F9E26 /* Networks.swift in Sources */, 2C134BA627553EC500DAFBDB /* Browser.swift in Sources */, 2CC89471269A334A00879245 /* UserDefaults.swift in Sources */, 2C78F8282683BDCC00C10670 /* Alert.swift in Sources */, @@ -1250,6 +1361,7 @@ 2C4768A9282598C5005E8D4D /* CoinDerivationCellView.swift in Sources */, 2CB4031D281D745D00BAEBEE /* NSTableView.swift in Sources */, 2CD0B3F726AC619900488D92 /* AddAccountOptionCellView.swift in Sources */, + 2CED86C52AF26327006F9E26 /* BundledNodes.swift in Sources */, 2C8944C52AEAFF97006A711F /* FixedWidthInteger.swift in Sources */, 0D059AD226C2796200EE3023 /* ApprovalSubject.swift in Sources */, 2C1995422674C4B900A8E370 /* ImportViewController.swift in Sources */, @@ -1280,6 +1392,7 @@ 2C8944CE2AEC34EB006A711F /* Blockies.swift in Sources */, 2C8A09DF267579EA00993638 /* AccountsListViewController.swift in Sources */, 2C917429267D2A6E00049075 /* Keychain.swift in Sources */, + 2C9B55D12AF2AE4B008BE899 /* BundledNetwork.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1298,6 +1411,7 @@ 2C40709027667A6600AB3D55 /* MultilineLabelTableViewCell.swift in Sources */, 2CF255A6275A48BB00AE54B9 /* GasService.swift in Sources */, 2C96D392276232A300687301 /* UITableView.swift in Sources */, + 2CED86C62AF26328006F9E26 /* BundledNodes.swift in Sources */, 2CF255A5275A48BB00AE54B9 /* ReviewRequester.swift in Sources */, 2CF255B6275A746000AE54B9 /* AccountsListViewController.swift in Sources */, 2C96D3A42763C6A800687301 /* UIView.swift in Sources */, @@ -1313,9 +1427,11 @@ 2CC6EF0D275E64810040CC62 /* UIViewController.swift in Sources */, 2C264BDD27B5AC5400234393 /* EthereumResponseToExtension.swift in Sources */, 2CF255A9275A48BB00AE54B9 /* Keychain.swift in Sources */, + 2CED86C42AF262E7006F9E26 /* Nodes.swift in Sources */, 2CF255A7275A48BB00AE54B9 /* PriceService.swift in Sources */, 2CF25598275A46D600AE54B9 /* Strings.swift in Sources */, 2C4768B52826ED83005E8D4D /* CoinType.swift in Sources */, + 2CED86C02AF25C32006F9E26 /* Networks.swift in Sources */, 2CF255AE275A48CF00AE54B9 /* Transaction.swift in Sources */, 2C96D38F2762317300687301 /* AccountTableViewCell.swift in Sources */, 2C264BEC27B6B50700234393 /* DappRequestProcessor.swift in Sources */, @@ -1330,6 +1446,7 @@ 2C8ED8DD2AEADDC400818D74 /* BigInt.swift in Sources */, 2C96D3A62763CCA000687301 /* Images.swift in Sources */, 2C264BD127B2F30C00234393 /* UnknownSafariRequest.swift in Sources */, + 2C9B55D22AF2AE4B008BE899 /* BundledNetwork.swift in Sources */, 2C96D39827623EC600687301 /* URL.swift in Sources */, 2CF255AD275A48CF00AE54B9 /* EthereumNetwork.swift in Sources */, 2CF2559C275A477F00AE54B9 /* ApprovalSubject.swift in Sources */, @@ -1372,11 +1489,24 @@ 2C2AA1D828AFB1AD00E35DBF /* MultipleResponseToExtension.swift in Sources */, 2CE0594327640EAB0042D844 /* ExtensionBridge.swift in Sources */, 2C264BDF27B5AC5400234393 /* EthereumResponseToExtension.swift in Sources */, + 2CED86BB2AF1820E006F9E26 /* Nodes.swift in Sources */, 2CC8C5AD276A7EF80083FB1B /* EthereumNetwork.swift in Sources */, 2C264BC427B2F2C100234393 /* EthereumSafariRequest.swift in Sources */, 2C264BBF27B2F25E00234393 /* SafariRequest.swift in Sources */, 2CE0593F27640E300042D844 /* SafariWebExtensionHandler.swift in Sources */, 2CE0594527640EF10042D844 /* ResponseToExtension.swift in Sources */, + 2CED86B72AF17D5A006F9E26 /* BundledNodes.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2CED869E2AF00BC9006F9E26 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2C9B55D32AF2AE4B008BE899 /* BundledNetwork.swift in Sources */, + 2CED86B02AF0167F006F9E26 /* EIP155ChainData.swift in Sources */, + 2CED86A52AF00BC9006F9E26 /* main.swift in Sources */, + 2CED86B32AF01F99006F9E26 /* String.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1430,7 +1560,7 @@ CODE_SIGN_ENTITLEMENTS = "Safari macOS/Safari.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 63; + CURRENT_PROJECT_VERSION = 64; DEVELOPMENT_TEAM = XWNXDSM6BU; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; @@ -1443,7 +1573,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.4; - MARKETING_VERSION = 2.0.19; + MARKETING_VERSION = 2.0.20; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -1464,7 +1594,7 @@ CODE_SIGN_ENTITLEMENTS = "Safari macOS/Safari.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 63; + CURRENT_PROJECT_VERSION = 64; DEVELOPMENT_TEAM = XWNXDSM6BU; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; @@ -1477,7 +1607,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.4; - MARKETING_VERSION = 2.0.19; + MARKETING_VERSION = 2.0.20; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -1617,7 +1747,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 63; + CURRENT_PROJECT_VERSION = 64; DEVELOPMENT_TEAM = XWNXDSM6BU; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "$(SRCROOT)/Tokenary macOS/Supporting Files/Info.plist"; @@ -1626,7 +1756,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.4; - MARKETING_VERSION = 2.0.19; + MARKETING_VERSION = 2.0.20; PRODUCT_BUNDLE_IDENTIFIER = mac.tokenary.io; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1645,7 +1775,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 63; + CURRENT_PROJECT_VERSION = 64; DEVELOPMENT_TEAM = XWNXDSM6BU; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "$(SRCROOT)/Tokenary macOS/Supporting Files/Info.plist"; @@ -1654,7 +1784,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.4; - MARKETING_VERSION = 2.0.19; + MARKETING_VERSION = 2.0.20; PRODUCT_BUNDLE_IDENTIFIER = mac.tokenary.io; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1671,7 +1801,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = "Tokenary iOS/Tokenary iOS.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 63; + CURRENT_PROJECT_VERSION = 64; DEVELOPMENT_TEAM = XWNXDSM6BU; INFOPLIST_FILE = "Tokenary iOS/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; @@ -1679,7 +1809,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.0.19; + MARKETING_VERSION = 2.0.20; PRODUCT_BUNDLE_IDENTIFIER = mac.tokenary.io; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -1700,7 +1830,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = "Tokenary iOS/Tokenary iOS.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 63; + CURRENT_PROJECT_VERSION = 64; DEVELOPMENT_TEAM = XWNXDSM6BU; INFOPLIST_FILE = "Tokenary iOS/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; @@ -1708,7 +1838,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.0.19; + MARKETING_VERSION = 2.0.20; PRODUCT_BUNDLE_IDENTIFIER = mac.tokenary.io; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -1727,7 +1857,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_ENTITLEMENTS = "Safari iOS/Safari iOS.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 63; + CURRENT_PROJECT_VERSION = 64; DEVELOPMENT_TEAM = XWNXDSM6BU; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Safari iOS/Info.plist"; @@ -1739,7 +1869,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.0.19; + MARKETING_VERSION = 2.0.20; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -1761,7 +1891,7 @@ CODE_SIGN_ENTITLEMENTS = "Safari iOS/Safari iOS.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 63; + CURRENT_PROJECT_VERSION = 64; DEVELOPMENT_TEAM = XWNXDSM6BU; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Safari iOS/Info.plist"; @@ -1773,7 +1903,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.0.19; + MARKETING_VERSION = 2.0.20; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -1790,6 +1920,41 @@ }; name = Release; }; + 2CED86A62AF00BC9006F9E26 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = XWNXDSM6BU; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 14.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 2CED86A72AF00BC9006F9E26 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = XWNXDSM6BU; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 14.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -1838,6 +2003,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 2CED86A82AF00BC9006F9E26 /* Build configuration list for PBXNativeTarget "tools" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2CED86A62AF00BC9006F9E26 /* Debug */, + 2CED86A72AF00BC9006F9E26 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 2C1995342674C4B900A8E370 /* Project object */; diff --git a/Tokenary.xcodeproj/xcshareddata/xcschemes/tools.xcscheme b/Tokenary.xcodeproj/xcshareddata/xcschemes/tools.xcscheme new file mode 100644 index 00000000..6756cc37 --- /dev/null +++ b/Tokenary.xcodeproj/xcshareddata/xcschemes/tools.xcscheme @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/bundled/BundledNodes.swift b/tools/bundled/BundledNodes.swift new file mode 100644 index 00000000..2e242cbc --- /dev/null +++ b/tools/bundled/BundledNodes.swift @@ -0,0 +1,77 @@ +import Foundation + +struct BundledNodes { + + static let dict: [Int: String] = [ + 1: "mainnet.infura.io/v3/", + 5: "goerli.infura.io/v3/", + 10: "optimism-mainnet.infura.io/v3/", + 25: "evm.cronos.org", + 56: "bsc-dataseed1.bnbchain.org", + 66: "exchainrpc.okex.org", + 69: "kovan.optimism.io/", + 77: "sokol.poa.network", + 97: "data-seed-prebsc-1-s1.bnbchain.org:8545", + 99: "core.poa.network", + 100: "rpc.gnosischain.com", + 122: "rpc.fuse.io", + 128: "http-mainnet.hecochain.com", + 137: "polygon-mainnet.infura.io/v3/", + 200: "arbitrum.xdaichain.com/", + 204: "opbnb-mainnet-rpc.bnbchain.org", + 250: "rpc.ftm.tools", + 280: "testnet.era.zksync.dev", + 288: "mainnet.boba.network", + 314: "api.node.glif.io/", + 324: "mainnet.era.zksync.io", + 338: "evm-t3.cronos.org", + 420: "goerli.optimism.io", + 424: "rpc.publicgoods.network", + 1001: "api.baobab.klaytn.net:8651", + 1088: "andromeda.metis.io/?owner=1088", + 1101: "zkevm-rpc.com", + 1284: "rpc.api.moonbeam.network", + 1285: "rpc.api.moonriver.moonbeam.network", + 1442: "rpc.public.zkevm-test.net", + 2221: "evm.testnet.kava.io", + 2222: "evm.kava.io", + 4002: "rpc.testnet.fantom.network", + 4337: "subnets.avax.network/beam/mainnet/rpc", + 5000: "rpc.mantle.xyz", + 5001: "rpc.testnet.mantle.xyz", + 5611: "opbnb-testnet-rpc.bnbchain.org", + 7700: "canto.slingshot.finance", + 8217: "1rpc.io/klay", + 8453: "mainnet.base.org/", + 10200: "rpc.chiadochain.net", + 42161: "arbitrum-mainnet.infura.io/v3/", + 42170: "nova.arbitrum.io/rpc", + 42220: "forno.celo.org", + 43113: "api.avax-test.network/ext/bc/C/rpc", + 43114: "api.avax.network/ext/bc/C/rpc", + 43288: "avax.boba.network", + 44787: "alfajores-forno.celo-testnet.org", + 58008: "sepolia.publicgoods.network", + 59140: "rpc.goerli.linea.build", + 59144: "rpc.linea.build", + 64240: "rpcapi.sonic.fantom.network/", + 80001: "rpc-mumbai.maticvigil.com", + 84531: "goerli.base.org", + 84532: "sepolia.base.org", + 421613: "goerli-rollup.arbitrum.io/rpc", + 421614: "sepolia-rollup.arbitrum.io/rpc", + 534351: "sepolia-rpc.scroll.io", + 534352: "rpc.scroll.io", + 7777777: "rpc.zora.energy/", + 11155111: "rpc.sepolia.org", + 245022926: "devnet.neonevm.org", + 245022934: "neon-proxy-mainnet.solana.p2p.org/", + 999999999: "sepolia.rpc.zora.energy", + 1313161554: "mainnet.aurora.dev", + 1313161555: "testnet.aurora.dev/", + 1666600000: "api.harmony.one", + 11297108099: "palm-testnet.infura.io/v3/", + 11297108109: "palm-mainnet.infura.io/v3/" + ] + +} diff --git a/tools/bundled/bundled-networks.json b/tools/bundled/bundled-networks.json new file mode 100644 index 00000000..b9e8475b --- /dev/null +++ b/tools/bundled/bundled-networks.json @@ -0,0 +1,326 @@ +{ + "1" : { + "n" : "Ethereum", + "s" : "ETH", + "o" : true + }, + "5" : { + "n" : "Goerli", + "s" : "ETH", + "t" : true + }, + "10" : { + "n" : "Optimism", + "s" : "ETH", + "o" : true + }, + "25" : { + "n" : "Cronos", + "s" : "CRO" + }, + "56" : { + "n" : "BNB Chain", + "s" : "BNB", + "o" : true + }, + "66" : { + "n" : "OKTC", + "s" : "OKT" + }, + "69" : { + "n" : "Optimism Kovan", + "s" : "ETH", + "t" : true + }, + "77" : { + "n" : "POA Network Sokol", + "s" : "SPOA", + "t" : true + }, + "97" : { + "n" : "BNB Chain Testnet", + "s" : "tBNB", + "t" : true + }, + "99" : { + "n" : "POA Network", + "s" : "POA" + }, + "100" : { + "n" : "Gnosis", + "s" : "xDai" + }, + "122" : { + "n" : "Fuse", + "s" : "FUSE" + }, + "128" : { + "n" : "Huobi ECO Chain", + "s" : "HT" + }, + "137" : { + "n" : "Polygon", + "s" : "MATIC", + "o" : true + }, + "200" : { + "n" : "Arbitrum on xDai", + "s" : "xDai" + }, + "204" : { + "n" : "opBNB", + "s" : "BNB", + "o" : true + }, + "250" : { + "n" : "Fantom Opera", + "s" : "FTM", + "o" : true + }, + "280" : { + "n" : "zkSync Era Testnet", + "s" : "ETH", + "t" : true + }, + "288" : { + "n" : "Boba", + "s" : "ETH", + "o" : true + }, + "314" : { + "n" : "Filecoin", + "s" : "FIL" + }, + "324" : { + "n" : "zkSync Era", + "s" : "ETH", + "o" : true + }, + "338" : { + "n" : "Cronos Testnet", + "s" : "TCRO", + "t" : true + }, + "420" : { + "n" : "Optimism Goerli", + "s" : "ETH", + "t" : true + }, + "424" : { + "n" : "Public Goods Network", + "s" : "ETH", + "o" : true + }, + "1001" : { + "n" : "Klaytn Baobab", + "s" : "KLAY", + "t" : true + }, + "1088" : { + "n" : "Metis Andromeda", + "s" : "METIS" + }, + "1101" : { + "n" : "Polygon zkEVM", + "s" : "ETH", + "o" : true + }, + "1284" : { + "n" : "Moonbeam", + "s" : "GLMR" + }, + "1285" : { + "n" : "Moonriver", + "s" : "MOVR" + }, + "1442" : { + "n" : "Polygon zkEVM Testnet", + "s" : "ETH", + "t" : true + }, + "2221" : { + "n" : "Kava Testnet", + "s" : "TKAVA", + "t" : true + }, + "2222" : { + "n" : "Kava", + "s" : "KAVA" + }, + "4002" : { + "n" : "Fantom Testnet", + "s" : "FTM", + "t" : true + }, + "4337" : { + "n" : "Beam", + "s" : "BEAM" + }, + "5000" : { + "n" : "Mantle", + "s" : "MNT" + }, + "5001" : { + "n" : "Mantle Testnet", + "s" : "MNT", + "t" : true + }, + "5611" : { + "n" : "opBNB Testnet", + "s" : "tBNB", + "t" : true + }, + "7700" : { + "n" : "Canto", + "s" : "CANTO" + }, + "8217" : { + "n" : "Klaytn", + "s" : "KLAY" + }, + "8453" : { + "n" : "Base", + "s" : "ETH", + "o" : true + }, + "10200" : { + "n" : "Gnosis Chiado", + "s" : "xDai", + "t" : true + }, + "42161" : { + "n" : "Arbitrum One", + "s" : "ETH", + "o" : true + }, + "42170" : { + "n" : "Arbitrum Nova", + "s" : "ETH", + "o" : true + }, + "42220" : { + "n" : "Celo", + "s" : "CELO" + }, + "43113" : { + "n" : "Avalanche Fuji", + "s" : "AVAX", + "t" : true + }, + "43114" : { + "n" : "Avalanche", + "s" : "AVAX", + "o" : true + }, + "43288" : { + "n" : "Boba Avax", + "s" : "BOBA" + }, + "44787" : { + "n" : "Celo Alfajores Testnet", + "s" : "CELO", + "t" : true + }, + "58008" : { + "n" : "Public Goods Network Sepolia", + "s" : "ETH", + "t" : true + }, + "59140" : { + "n" : "Linea Testnet", + "s" : "ETH", + "t" : true + }, + "59144" : { + "n" : "Linea", + "s" : "ETH", + "o" : true + }, + "64240" : { + "n" : "Fantom Sonic Open", + "s" : "FTM", + "t" : true + }, + "80001" : { + "n" : "Polygon Mumbai", + "s" : "MATIC", + "t" : true + }, + "84531" : { + "n" : "Base Goerli", + "s" : "ETH", + "t" : true + }, + "84532" : { + "n" : "Base Sepolia", + "s" : "ETH", + "t" : true + }, + "421613" : { + "n" : "Arbitrum Goerli", + "s" : "AGOR", + "t" : true + }, + "421614" : { + "n" : "Arbitrum Sepolia", + "s" : "ETH", + "t" : true + }, + "534351" : { + "n" : "Scroll Sepolia", + "s" : "ETH", + "t" : true + }, + "534352" : { + "n" : "Scroll", + "s" : "ETH", + "o" : true + }, + "7777777" : { + "n" : "Zora", + "s" : "ETH", + "o" : true + }, + "11155111" : { + "n" : "Sepolia", + "s" : "ETH", + "t" : true + }, + "245022926" : { + "n" : "Neon EVM DevNet", + "s" : "NEON", + "t" : true + }, + "245022934" : { + "n" : "Neon EVM", + "s" : "NEON" + }, + "999999999" : { + "n" : "Zora Sepolia", + "s" : "ETH", + "t" : true + }, + "1313161554" : { + "n" : "Aurora", + "s" : "ETH", + "o" : true + }, + "1313161555" : { + "n" : "Aurora Testnet", + "s" : "ETH", + "t" : true + }, + "1666600000" : { + "n" : "Harmony", + "s" : "ONE" + }, + "11297108099" : { + "n" : "Palm Testnet", + "s" : "PALM", + "t" : true + }, + "11297108109" : { + "n" : "Palm", + "s" : "PALM" + } +} diff --git a/tools/helpers/nodes-to-bundle.json b/tools/helpers/nodes-to-bundle.json new file mode 100644 index 00000000..2f65661c --- /dev/null +++ b/tools/helpers/nodes-to-bundle.json @@ -0,0 +1,71 @@ +{ + "1" : "mainnet.infura.io/v3/", + "5" : "goerli.infura.io/v3/", + "10" : "optimism-mainnet.infura.io/v3/", + "25" : "evm.cronos.org", + "56" : "bsc-dataseed1.bnbchain.org", + "66" : "exchainrpc.okex.org", + "69" : "kovan.optimism.io/", + "77" : "sokol.poa.network", + "97" : "data-seed-prebsc-1-s1.bnbchain.org:8545", + "99" : "core.poa.network", + "100" : "rpc.gnosischain.com", + "122" : "rpc.fuse.io", + "128" : "http-mainnet.hecochain.com", + "137" : "polygon-mainnet.infura.io/v3/", + "200" : "arbitrum.xdaichain.com/", + "204" : "opbnb-mainnet-rpc.bnbchain.org", + "250" : "rpc.ftm.tools", + "280" : "testnet.era.zksync.dev", + "288" : "mainnet.boba.network", + "314" : "api.node.glif.io/", + "324" : "mainnet.era.zksync.io", + "338" : "evm-t3.cronos.org", + "420" : "goerli.optimism.io", + "424" : "rpc.publicgoods.network", + "1001" : "api.baobab.klaytn.net:8651", + "1088" : "andromeda.metis.io/?owner=1088", + "1101" : "zkevm-rpc.com", + "1284" : "rpc.api.moonbeam.network", + "1285" : "rpc.api.moonriver.moonbeam.network", + "1442" : "rpc.public.zkevm-test.net", + "2221" : "evm.testnet.kava.io", + "2222" : "evm.kava.io", + "4002" : "rpc.testnet.fantom.network", + "4337" : "subnets.avax.network/beam/mainnet/rpc", + "5000" : "rpc.mantle.xyz", + "5001" : "rpc.testnet.mantle.xyz", + "5611" : "opbnb-testnet-rpc.bnbchain.org", + "7700" : "canto.slingshot.finance", + "8217" : "1rpc.io/klay", + "8453" : "mainnet.base.org/", + "10200" : "rpc.chiadochain.net", + "42161" : "arbitrum-mainnet.infura.io/v3/", + "42170" : "nova.arbitrum.io/rpc", + "42220" : "forno.celo.org", + "43113" : "api.avax-test.network/ext/bc/C/rpc", + "43114" : "api.avax.network/ext/bc/C/rpc", + "43288" : "avax.boba.network", + "44787" : "alfajores-forno.celo-testnet.org", + "58008" : "sepolia.publicgoods.network", + "59140" : "rpc.goerli.linea.build", + "59144" : "rpc.linea.build", + "64240" : "rpcapi.sonic.fantom.network/", + "80001" : "rpc-mumbai.maticvigil.com", + "84531" : "goerli.base.org", + "84532" : "sepolia.base.org", + "421613" : "goerli-rollup.arbitrum.io/rpc", + "421614" : "sepolia-rollup.arbitrum.io/rpc", + "534351" : "sepolia-rpc.scroll.io", + "534352" : "rpc.scroll.io", + "7777777" : "rpc.zora.energy/", + "11155111" : "rpc.sepolia.org", + "245022926" : "devnet.neonevm.org", + "245022934" : "neon-proxy-mainnet.solana.p2p.org/", + "999999999" : "sepolia.rpc.zora.energy", + "1313161554" : "mainnet.aurora.dev", + "1313161555" : "testnet.aurora.dev/", + "1666600000" : "api.harmony.one", + "11297108099" : "palm-testnet.infura.io/v3/", + "11297108109" : "palm-mainnet.infura.io/v3/" +} diff --git a/tools/main.swift b/tools/main.swift new file mode 100644 index 00000000..e6a940de --- /dev/null +++ b/tools/main.swift @@ -0,0 +1,87 @@ +// Copyright © 2023 Tokenary. All rights reserved. + +import Foundation + +let semaphore = DispatchSemaphore(value: 0) + +let projectDir = FileManager.default.currentDirectoryPath +let base = "\(projectDir)/tools/" + +let bundledNetworksFileURL = URL(fileURLWithPath: base + "bundled/bundled-networks.json") +let bundledNodesFileURL = URL(fileURLWithPath: base + "bundled/BundledNodes.swift") +let nodesToBundleFileURL = URL(fileURLWithPath: base + "helpers/nodes-to-bundle.json") + +let https = "https://" + +let encoder = JSONEncoder() +encoder.outputFormatting = [.prettyPrinted, .withoutEscapingSlashes, .sortedKeys] + +func fetchChains(completion: @escaping ([EIP155ChainData]) -> Void) { + URLSession.shared.dataTask(with: URL(string: "https://chainid.network/chains.json")!) { (data, _, _) in + completion(try! JSONDecoder().decode([EIP155ChainData].self, from: data!)) + }.resume() +} + +fetchChains { chains in + let currentNetworksData = try! Data(contentsOf: bundledNetworksFileURL) + let currentNodesData = try! Data(contentsOf: nodesToBundleFileURL) + + let currentNetworks = try! JSONDecoder().decode([Int: BundledNetwork].self, from: currentNetworksData) + let currentNodes = try! JSONDecoder().decode([String: String].self, from: currentNodesData) + + let currentIds = Set(currentNetworks.keys) + let newChainsIds = Set([1284, 1285, 288, 43288, 25, 338]) + + let newChains = chains.filter { chain in + let isEIP3091 = chain.explorers?.contains(where: { $0.standard == "EIP3091" }) == true + let allowNoEIP3091 = true + if newChainsIds.contains(chain.chainId) && + !currentIds.contains(chain.chainId) && + chain.rpc.contains(where: { $0.hasPrefix(https) }) && + chain.redFlags == nil && + chain.status != "deprecated" && + chain.nativeCurrency.decimals == 18 && + (isEIP3091 || allowNoEIP3091) { + return true + } else { + return false + } + } + + var updatedNetworks = currentNetworks + var updatedNodes = currentNodes + + newChains.forEach { chain in + updatedNetworks[chain.chainId] = BundledNetwork(name: chain.name, symbol: chain.nativeCurrency.symbol, isTest: true) + updatedNodes[String(chain.chainId)] = String(chain.rpc.first(where: { $0.hasPrefix(https) })!.dropFirst(https.count)) + } + + let data = (try! encoder.encode(updatedNetworks)) + "\n".data(using: .utf8)! + try! data.write(to: bundledNetworksFileURL) + updateNodesFiles(nodes: updatedNodes) + semaphore.signal() +} + +func updateNodesFiles(nodes: [String: String]) { + let dictData = try! JSONSerialization.data(withJSONObject: nodes, options: [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes]) + "\n".data(using: .utf8)! + try! dictData.write(to: nodesToBundleFileURL) + + let dictString = nodes.sorted(by: { Int($0.key)! < Int($1.key)! }).map { "\($0.key): \"\($0.value)\"" }.joined(separator: ",\n ") + let contents = """ + import Foundation + + struct BundledNodes { + + static let dict: [Int: String] = [ + \(dictString) + ] + + } + + """ + + try! contents.data(using: .utf8)?.write(to: bundledNodesFileURL) +} + +semaphore.wait() +print("🟢 all done") diff --git a/tools/models/BundledNetwork.swift b/tools/models/BundledNetwork.swift new file mode 100644 index 00000000..04e66379 --- /dev/null +++ b/tools/models/BundledNetwork.swift @@ -0,0 +1,46 @@ +// Copyright © 2023 Tokenary. All rights reserved. + +import Foundation + +struct BundledNetwork: Codable { + + let name: String + let symbol: String + let isTest: Bool + let okToShowPriceForSymbol: Bool + + private enum CodingKeys: String, CodingKey { + case name = "n" + case symbol = "s" + case isTest = "t" + case okToShowPriceForSymbol = "o" + } + + init(name: String, symbol: String, isTest: Bool, okToShowPriceForSymbol: Bool) { + self.name = name + self.symbol = symbol + self.isTest = isTest + self.okToShowPriceForSymbol = okToShowPriceForSymbol + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + name = try container.decode(String.self, forKey: .name) + symbol = try container.decode(String.self, forKey: .symbol) + isTest = try container.decodeIfPresent(Bool.self, forKey: .isTest) ?? false + if isTest { + okToShowPriceForSymbol = false + } else { + okToShowPriceForSymbol = try container.decodeIfPresent(Bool.self, forKey: .okToShowPriceForSymbol) ?? false + } + } + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(name, forKey: .name) + try container.encode(symbol, forKey: .symbol) + if isTest { try container.encode(isTest, forKey: .isTest) } + if okToShowPriceForSymbol { try container.encode(okToShowPriceForSymbol, forKey: .okToShowPriceForSymbol) } + } + +} diff --git a/tools/models/EIP155ChainData.swift b/tools/models/EIP155ChainData.swift new file mode 100644 index 00000000..ea9fdc26 --- /dev/null +++ b/tools/models/EIP155ChainData.swift @@ -0,0 +1,63 @@ +// Copyright © 2023 Tokenary. All rights reserved. + +import Foundation + +// https://github.com/ethereum-lists/chains/blob/master/tools/schema/chainSchema.json + +struct EIP155ChainData: Codable { + + let name: String // Name of the Network + let shortName: String + let chain: String + let chainId: Int + let networkId: Int + let rpc: [String] + let faucets: [String] + let infoURL: String + let nativeCurrency: NativeCurrency + + let title: String? + let icon: String? // Icon type + let features: [Feature]? + let slip44: Int? + let ens: ENS? + let explorers: [Explorer]? + let parent: Parent? + let status: String? // Chain status + let redFlags: [RedFlag]? + + struct NativeCurrency: Codable { + let name: String // Name of the Native Currency + let symbol: String // Symbol of the Native Currency + let decimals: Int // Decimal points supported + } + + struct Feature: Codable { + let name: String // Feature name - e.g. EIP155 + } + + struct ENS: Codable { + let registry: String + } + + struct Explorer: Codable { + let name: String + let url: String + let standard: String? // EIP3091 or none + } + + struct Parent: Codable { + let type: String + let chain: String + let bridges: [Bridge]? + + struct Bridge: Codable { + let url: String + } + } + + enum RedFlag: String, Codable { + case reusedChainId = "reusedChainId" + } + +}