Repository: petejkim/metamask-mobile Branch: master Commit: d307dd64939d Files: 79 Total size: 5.4 MB Directory structure: gitextract_v8ksmv8r/ ├── .babelrc ├── .buckconfig ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .watchmanconfig ├── LICENSE ├── README.md ├── android/ │ ├── app/ │ │ ├── BUCK │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src/ │ │ └── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── com/ │ │ │ └── nabi/ │ │ │ ├── MainActivity.java │ │ │ └── MainApplication.java │ │ └── res/ │ │ └── values/ │ │ ├── strings.xml │ │ └── styles.xml │ ├── build.gradle │ ├── gradle/ │ │ └── wrapper/ │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradle.properties │ ├── gradlew │ ├── gradlew.bat │ ├── keystores/ │ │ ├── BUCK │ │ └── debug.keystore.properties │ └── settings.gradle ├── app.json ├── index.android.js ├── index.ios.js ├── ios/ │ ├── Nabi/ │ │ ├── AppDelegate.swift │ │ ├── AppProtocol.swift │ │ ├── Assets.xcassets/ │ │ │ └── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ └── LaunchScreen.xib │ │ ├── Info.plist │ │ └── Nabi-Bridging-Header.h │ ├── Nabi.xcodeproj/ │ │ ├── project.pbxproj │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── Nabi.xcscheme │ ├── NabiTests/ │ │ ├── Info.plist │ │ └── NabiTests.swift │ ├── NabiUITests/ │ │ ├── Info.plist │ │ └── NabiUITests.swift │ └── vendor/ │ └── WKWebViewWithURLProtocol/ │ ├── NSURLProtocol+WKWebViewSupport.h │ └── NSURLProtocol+WKWebViewSupport.m ├── package.json ├── rn-cli.config.js ├── src/ │ ├── @types/ │ │ ├── react-native-navigation.d.ts │ │ └── react-native-wkwebview-reborn.d.ts │ ├── components/ │ │ ├── BrowserWindow.tsx │ │ ├── LocationBar.tsx │ │ ├── MetaMaskBackground.tsx │ │ └── PageLoadProgress.tsx │ ├── constants.ts │ ├── index.ts │ ├── injections/ │ │ ├── contentScript.ts │ │ ├── metaMaskBackground.ts │ │ ├── metaMaskPopup.ts │ │ └── types.ts │ ├── ipc.ts │ ├── screens/ │ │ ├── MetaMaskScreen.tsx │ │ ├── RootScreen.tsx │ │ └── index.ts │ ├── util.test.ts │ └── util.ts ├── tsconfig.json ├── tslint.json └── web/ ├── metamask/ │ ├── _locales/ │ │ ├── en/ │ │ │ └── messages.json │ │ ├── es/ │ │ │ └── messages.json │ │ ├── es_419/ │ │ │ └── messages.json │ │ ├── ja/ │ │ │ └── messages.json │ │ └── zh_CN/ │ │ └── messages.json │ ├── background.html │ ├── fonts/ │ │ └── Montserrat/ │ │ └── OFL.txt │ ├── manifest.json │ ├── popup.html │ └── scripts/ │ ├── background.js │ ├── contentscript.js │ ├── inpage.js │ └── popup.js └── vendor/ ├── asmcrypto-0.0.11.js └── webcrypto-liner.shim-0.1.22.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .babelrc ================================================ { "presets": ["react-native"] } ================================================ FILE: .buckconfig ================================================ [android] target = Google Inc.:Google APIs:23 [maven_repositories] central = https://repo1.maven.org/maven2 ================================================ FILE: .flowconfig ================================================ [ignore] ; We fork some components by platform .*/*[.]android.js ; Ignore "BUCK" generated dirs /\.buckd/ ; Ignore unexpected extra "@providesModule" .*/node_modules/.*/node_modules/fbjs/.* ; Ignore duplicate module providers ; For RN Apps installed via npm, "Libraries" folder is inside ; "node_modules/react-native" but in the source repo it is in the root .*/Libraries/react-native/React.js .*/Libraries/react-native/ReactNative.js [include] [libs] node_modules/react-native/Libraries/react-native/react-native-interface.js node_modules/react-native/flow flow/ [options] emoji=true module.system=haste experimental.strict_type_args=true munge_underscores=true module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' suppress_type=$FlowIssue suppress_type=$FlowFixMe suppress_type=$FixMe suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-5]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-5]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError unsafe.enable_getters_and_setters=true [version] ^0.45.0 ================================================ FILE: .gitattributes ================================================ *.pbxproj -text ================================================ FILE: .gitignore ================================================ # OSX # .DS_Store # Xcode # build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata *.xccheckout *.moved-aside DerivedData *.hmap *.ipa *.xcuserstate project.xcworkspace # Android/IntelliJ # build/ .idea .gradle local.properties *.iml # node.js # node_modules/ npm-debug.log yarn-error.log # BUCK buck-out/ \.buckd/ *.keystore # fastlane # # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the # screenshots whenever they are needed. # For more information about the recommended setup visit: # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md fastlane/report.xml fastlane/Preview.html fastlane/screenshots ================================================ FILE: .watchmanconfig ================================================ {} ================================================ FILE: LICENSE ================================================ The Ethereum Project Contributor Asset Distribution Terms ( MIT + Share-alike ) Copyright (c) 2016-2017 MetaMask Copyright (c) 2017 Peter Jihoon Kim Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. These licence terms have been adapted from the MIT licence. ================================================ FILE: README.md ================================================ MetaMask for Mobile =================== ![Screenshot](https://raw.githubusercontent.com/petejkim/metamask-mobile/master/misc/metamask-mobile.gif) **This project is very EXPERIMENTAL, use it at your own risk.** A mobile port of MetaMask. Only built/tested for iOS at the moment. ### Requirements * Xcode >= 8.x * Node.js >= 8.x ### Instructions ``` $ cd metamask-mobile $ npm -g install yarn $ yarn install $ yarn run-ios ``` ================================================ FILE: android/app/BUCK ================================================ # To learn about Buck see [Docs](https://buckbuild.com/). # To run your application with Buck: # - install Buck # - `npm start` - to start the packager # - `cd android` # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck # - `buck install -r android/app` - compile, install and run application # lib_deps = [] for jarfile in glob(['libs/*.jar']): name = 'jars__' + jarfile[jarfile.rindex('/') + 1: jarfile.rindex('.jar')] lib_deps.append(':' + name) prebuilt_jar( name = name, binary_jar = jarfile, ) for aarfile in glob(['libs/*.aar']): name = 'aars__' + aarfile[aarfile.rindex('/') + 1: aarfile.rindex('.aar')] lib_deps.append(':' + name) android_prebuilt_aar( name = name, aar = aarfile, ) android_library( name = "all-libs", exported_deps = lib_deps, ) android_library( name = "app-code", srcs = glob([ "src/main/java/**/*.java", ]), deps = [ ":all-libs", ":build_config", ":res", ], ) android_build_config( name = "build_config", package = "com.nabi", ) android_resource( name = "res", package = "com.nabi", res = "src/main/res", ) android_binary( name = "app", keystore = "//android/keystores:debug", manifest = "src/main/AndroidManifest.xml", package_type = "debug", deps = [ ":app-code", ], ) ================================================ FILE: android/app/build.gradle ================================================ apply plugin: "com.android.application" import com.android.build.OutputFile /** * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets * and bundleReleaseJsAndAssets). * These basically call `react-native bundle` with the correct arguments during the Android build * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the * bundle directly from the development server. Below you can see all the possible configurations * and their defaults. If you decide to add a configuration block, make sure to add it before the * `apply from: "../../node_modules/react-native/react.gradle"` line. * * project.ext.react = [ * // the name of the generated asset file containing your JS bundle * bundleAssetName: "index.android.bundle", * * // the entry file for bundle generation * entryFile: "index.android.js", * * // whether to bundle JS and assets in debug mode * bundleInDebug: false, * * // whether to bundle JS and assets in release mode * bundleInRelease: true, * * // whether to bundle JS and assets in another build variant (if configured). * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants * // The configuration property can be in the following formats * // 'bundleIn${productFlavor}${buildType}' * // 'bundleIn${buildType}' * // bundleInFreeDebug: true, * // bundleInPaidRelease: true, * // bundleInBeta: true, * * // the root of your project, i.e. where "package.json" lives * root: "../../", * * // where to put the JS bundle asset in debug mode * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", * * // where to put the JS bundle asset in release mode * jsBundleDirRelease: "$buildDir/intermediates/assets/release", * * // where to put drawable resources / React Native assets, e.g. the ones you use via * // require('./image.png')), in debug mode * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", * * // where to put drawable resources / React Native assets, e.g. the ones you use via * // require('./image.png')), in release mode * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", * * // by default the gradle tasks are skipped if none of the JS files or assets change; this means * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to * // date; if you have any other folders that you want to ignore for performance reasons (gradle * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ * // for example, you might want to remove it from here. * inputExcludes: ["android/**", "ios/**"], * * // override which node gets called and with what additional arguments * nodeExecutableAndArgs: ["node"], * * // supply additional arguments to the packager * extraPackagerArgs: [] * ] */ apply from: "../../node_modules/react-native/react.gradle" /** * Set this to true to create two separate APKs instead of one: * - An APK that only works on ARM devices * - An APK that only works on x86 devices * The advantage is the size of the APK is reduced by about 4MB. * Upload all the APKs to the Play Store and people will download * the correct one based on the CPU architecture of their device. */ def enableSeparateBuildPerCPUArchitecture = false /** * Run Proguard to shrink the Java bytecode in release builds. */ def enableProguardInReleaseBuilds = false android { compileSdkVersion 23 buildToolsVersion "23.0.1" defaultConfig { applicationId "com.nabi" minSdkVersion 16 targetSdkVersion 22 versionCode 1 versionName "1.0" ndk { abiFilters "armeabi-v7a", "x86" } } splits { abi { reset() enable enableSeparateBuildPerCPUArchitecture universalApk false // If true, also generate a universal APK include "armeabi-v7a", "x86" } } buildTypes { release { minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } // applicationVariants are e.g. debug, release applicationVariants.all { variant -> variant.outputs.each { output -> // For each separate APK per architecture, set a unique version code as described here: // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits def versionCodes = ["armeabi-v7a":1, "x86":2] def abi = output.getFilter(OutputFile.ABI) if (abi != null) { // null for the universal-debug, universal-release variants output.versionCodeOverride = versionCodes.get(abi) * 1048576 + defaultConfig.versionCode } } } } dependencies { compile project(':react-native-navigation') compile fileTree(dir: "libs", include: ["*.jar"]) compile "com.android.support:appcompat-v7:23.0.1" compile "com.facebook.react:react-native:+" // From node_modules } // Run this once to be able to run the application with BUCK // puts all compile dependencies into folder libs for BUCK to use task copyDownloadableDepsToLibs(type: Copy) { from configurations.compile into 'libs' } ================================================ FILE: android/app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} # Disabling obfuscation is useful if you collect stack traces from production crashes # (unless you are using a system that supports de-obfuscate the stack traces). -dontobfuscate # React Native # Keep our interfaces so they can be used by other ProGuard rules. # See http://sourceforge.net/p/proguard/bugs/466/ -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip # Do not strip any method/class that is annotated with @DoNotStrip -keep @com.facebook.proguard.annotations.DoNotStrip class * -keep @com.facebook.common.internal.DoNotStrip class * -keepclassmembers class * { @com.facebook.proguard.annotations.DoNotStrip *; @com.facebook.common.internal.DoNotStrip *; } -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * { void set*(***); *** get*(); } -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; } -keep class * extends com.facebook.react.bridge.NativeModule { *; } -keepclassmembers,includedescriptorclasses class * { native ; } -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; } -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; } -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; } -dontwarn com.facebook.react.** # TextLayoutBuilder uses a non-public Android constructor within StaticLayout. # See libs/proxy/src/main/java/com/facebook/fbui/textlayoutbuilder/proxy for details. -dontwarn android.text.StaticLayout # okhttp -keepattributes Signature -keepattributes *Annotation* -keep class okhttp3.** { *; } -keep interface okhttp3.** { *; } -dontwarn okhttp3.** # okio -keep class sun.misc.Unsafe { *; } -dontwarn java.nio.file.* -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement -dontwarn okio.** ================================================ FILE: android/app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: android/app/src/main/java/com/nabi/MainActivity.java ================================================ package com.nabi; import com.facebook.react.ReactActivity; public class MainActivity extends ReactActivity { /** * Returns the name of the main component registered from JavaScript. * This is used to schedule rendering of the component. */ @Override protected String getMainComponentName() { return "Nabi"; } } ================================================ FILE: android/app/src/main/java/com/nabi/MainApplication.java ================================================ package com.nabi; import android.app.Application; import com.facebook.react.ReactApplication; import com.reactnativenavigation.NavigationReactPackage; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; import com.facebook.soloader.SoLoader; import java.util.Arrays; import java.util.List; public class MainApplication extends Application implements ReactApplication { private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List getPackages() { return Arrays.asList( new MainReactPackage(), new NavigationReactPackage() ); } }; @Override public ReactNativeHost getReactNativeHost() { return mReactNativeHost; } @Override public void onCreate() { super.onCreate(); SoLoader.init(this, /* native exopackage */ false); } } ================================================ FILE: android/app/src/main/res/values/strings.xml ================================================ Nabi ================================================ FILE: android/app/src/main/res/values/styles.xml ================================================ ================================================ FILE: android/build.gradle ================================================ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { mavenLocal() jcenter() maven { // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm url "$rootDir/../node_modules/react-native/android" } } } ================================================ FILE: android/gradle/wrapper/gradle-wrapper.properties ================================================ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip ================================================ FILE: android/gradle.properties ================================================ # Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx10248m -XX:MaxPermSize=256m # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true android.useDeprecatedNdk=true ================================================ FILE: android/gradlew ================================================ #!/usr/bin/env bash ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS="" APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn ( ) { echo "$*" } die ( ) { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; esac # For Cygwin, ensure paths are in UNIX format before anything is touched. if $cygwin ; then [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` fi # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >&- APP_HOME="`pwd -P`" cd "$SAVED" >&- CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules function splitJvmOpts() { JVM_OPTS=("$@") } eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" ================================================ FILE: android/gradlew.bat ================================================ @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS= set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windowz variants if not "%OS%" == "Windows_NT" goto win9xME_args if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* goto execute :4NT_args @rem Get arguments from the 4NT Shell from JP Software set CMD_LINE_ARGS=%$ :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: android/keystores/BUCK ================================================ keystore( name = "debug", properties = "debug.keystore.properties", store = "debug.keystore", visibility = [ "PUBLIC", ], ) ================================================ FILE: android/keystores/debug.keystore.properties ================================================ key.store=debug.keystore key.alias=androiddebugkey key.store.password=android key.alias.password=android ================================================ FILE: android/settings.gradle ================================================ rootProject.name = 'Nabi' include ':react-native-navigation' project(':react-native-navigation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-navigation/android/app') include ':app' ================================================ FILE: app.json ================================================ { "name": "Nabi", "displayName": "Nabi" } ================================================ FILE: index.android.js ================================================ import { startApp } from './src' startApp() ================================================ FILE: index.ios.js ================================================ import { startApp } from './src' startApp() ================================================ FILE: ios/Nabi/AppDelegate.swift ================================================ import UIKit import WebKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { URLProtocol.wk_registerScheme("app") URLProtocol.wk_registerScheme("about") URLProtocol.registerClass(AppProtocol.self) let jsCodeLocation = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index.ios", fallbackResource: nil) self.window = UIWindow(frame: UIScreen.main.bounds) self.window?.backgroundColor = UIColor.white RCCManager.sharedInstance().initBridge(withBundleURL: jsCodeLocation) return true } func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. } func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. } func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } } ================================================ FILE: ios/Nabi/AppProtocol.swift ================================================ import UIKit class AppProtocol: URLProtocol { override class func canInit(with request: URLRequest) -> Bool { return request.url!.scheme == "app" || (request.url!.scheme == "about" && request.url!.host == "metamask") } override class func canonicalRequest(for request: URLRequest) -> URLRequest { return request; } override func startLoading() { let url = self.request.url! DispatchQueue.global(qos: .userInitiated).async { let fileName = "\(Bundle.main.bundlePath)/web/\(url.host!)\(url.path)" print("loading \(url.absoluteString) --> \(fileName)") let fileURL = URL(fileURLWithPath: fileName) let data = try? Data(contentsOf: fileURL) let ext = fileURL.pathExtension let response = URLResponse.init(url: self.request.url!, mimeType: mimeType(ext: ext), expectedContentLength: data!.count, textEncodingName: isTextFile(ext: ext) ? "utf-8" : nil) DispatchQueue.main.async { let client = self.client! client.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) client.urlProtocol(self, didLoad: data!) client.urlProtocolDidFinishLoading(self) } } } override func stopLoading() { } } func mimeType(ext: String) -> String { switch ext { case "css": return "text/css" case "gif": return "image/gif" case "html", "htm": return "text/html" case "jpeg", "jpg": return "image/jpeg" case "js": return "application/javascript" case "json", "map": return "application/json" case "png": return "image/png" case "svg": return "image/svg+xml" case "text", "txt": return "text/plain" case "ttf": return "application/font-sfnt" case "woff": return "application/font-woff" default: return "application/octet-stream" } } func isTextFile(ext: String) -> Bool { return ["css", "html", "htm", "js", "json", "map", "svg", "text", "txt"].contains(ext) } ================================================ FILE: ios/Nabi/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: ios/Nabi/Base.lproj/LaunchScreen.xib ================================================ ================================================ FILE: ios/Nabi/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleDisplayName Nabi CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS NSAppTransportSecurity NSAllowsArbitraryLoadsInWebContent NSExceptionDomains localhost NSExceptionAllowsInsecureHTTPLoads NSLocationWhenInUseUsageDescription UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance ================================================ FILE: ios/Nabi/Nabi-Bridging-Header.h ================================================ // // Use this file to import your target's public headers that you would like to expose to Swift. // #import "NSURLProtocol+WKWebViewSupport.h" #import #import "RCCManager.h" ================================================ FILE: ios/Nabi.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ E91D41411EE4233F009BE67F /* web in Resources */ = {isa = PBXBuildFile; fileRef = E91D41401EE4233F009BE67F /* web */; }; E91D41891EE4241F009BE67F /* NSURLProtocol+WKWebViewSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = E91D41881EE4241F009BE67F /* NSURLProtocol+WKWebViewSupport.m */; }; E91D41C01EE42AD6009BE67F /* AppProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91D41BF1EE42AD6009BE67F /* AppProtocol.swift */; }; E99BB9F01EE411AA00915720 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E99BB9EF1EE411AA00915720 /* AppDelegate.swift */; }; E99BB9F71EE411AA00915720 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E99BB9F61EE411AA00915720 /* Assets.xcassets */; }; E99BBA051EE411AA00915720 /* NabiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E99BBA041EE411AA00915720 /* NabiTests.swift */; }; E99BBA101EE411AA00915720 /* NabiUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E99BBA0F1EE411AA00915720 /* NabiUITests.swift */; }; E99BBA3F1EE4135900915720 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBA3E1EE4135900915720 /* WebKit.framework */; }; E99BBB301EE420A600915720 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBAA31EE41FEA00915720 /* libReact.a */; }; E99BBB511EE420B100915720 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBAB71EE4200A00915720 /* libRCTActionSheet.a */; }; E99BBB521EE420B600915720 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBABE1EE4201E00915720 /* libRCTAnimation.a */; }; E99BBB531EE420BC00915720 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBAC61EE4202500915720 /* libRCTGeolocation.a */; }; E99BBB541EE420C200915720 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBACD1EE4202B00915720 /* libRCTImage.a */; }; E99BBB551EE420C700915720 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBAD61EE4203500915720 /* libRCTLinking.a */; }; E99BBB561EE420D400915720 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBADF1EE4203B00915720 /* libRCTNetwork.a */; }; E99BBB571EE420D800915720 /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBAE81EE4204700915720 /* libRCTSettings.a */; }; E99BBB581EE420DF00915720 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBAF11EE4204D00915720 /* libRCTText.a */; }; E99BBB591EE420E400915720 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBAF91EE4205000915720 /* libRCTVibration.a */; }; E99BBB5A1EE420E900915720 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBB001EE4205500915720 /* libRCTWebSocket.a */; }; E99BBB5B1EE420F400915720 /* libRCTWKWebView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBB081EE4205900915720 /* libRCTWKWebView.a */; }; E99BBB5C1EE420FB00915720 /* libReactNativeNavigation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E99BBB1A1EE4207300915720 /* libReactNativeNavigation.a */; }; E99BBB7D1EE4227100915720 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = E99BBB7B1EE4227100915720 /* LaunchScreen.xib */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ E99BBA011EE411AA00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BB9E41EE411AA00915720 /* Project object */; proxyType = 1; remoteGlobalIDString = E99BB9EB1EE411AA00915720; remoteInfo = Nabi; }; E99BBA0C1EE411AA00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BB9E41EE411AA00915720 /* Project object */; proxyType = 1; remoteGlobalIDString = E99BB9EB1EE411AA00915720; remoteInfo = Nabi; }; E99BBAA21EE41FEA00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBA971EE41FEA00915720 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; remoteInfo = React; }; E99BBAA41EE41FEA00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBA971EE41FEA00915720 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A28131D9B038B00D4039D; remoteInfo = "React-tvOS"; }; E99BBAA61EE41FEA00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBA971EE41FEA00915720 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3D3C059A1DE3340900C268FA; remoteInfo = yoga; }; E99BBAA81EE41FEA00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBA971EE41FEA00915720 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3D3C06751DE3340C00C268FA; remoteInfo = "yoga-tvOS"; }; E99BBAAA1EE41FEA00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBA971EE41FEA00915720 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3D3CD9251DE5FBEC00167DC4; remoteInfo = cxxreact; }; E99BBAAC1EE41FEA00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBA971EE41FEA00915720 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3D3CD9321DE5FBEE00167DC4; remoteInfo = "cxxreact-tvOS"; }; E99BBAAE1EE41FEA00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBA971EE41FEA00915720 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3D3CD90B1DE5FBD600167DC4; remoteInfo = jschelpers; }; E99BBAB01EE41FEA00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBA971EE41FEA00915720 /* React.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3D3CD9181DE5FBD800167DC4; remoteInfo = "jschelpers-tvOS"; }; E99BBAB61EE4200A00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAB21EE4200A00915720 /* RCTActionSheet.xcodeproj */; proxyType = 2; remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTActionSheet; }; E99BBABD1EE4201E00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAB81EE4201E00915720 /* RCTAnimation.xcodeproj */; proxyType = 2; remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTAnimation; }; E99BBABF1EE4201E00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAB81EE4201E00915720 /* RCTAnimation.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A28201D9B03D100D4039D; remoteInfo = "RCTAnimation-tvOS"; }; E99BBAC51EE4202500915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAC11EE4202500915720 /* RCTGeolocation.xcodeproj */; proxyType = 2; remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTGeolocation; }; E99BBACC1EE4202B00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAC71EE4202B00915720 /* RCTImage.xcodeproj */; proxyType = 2; remoteGlobalIDString = 58B5115D1A9E6B3D00147676; remoteInfo = RCTImage; }; E99BBACE1EE4202B00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAC71EE4202B00915720 /* RCTImage.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A283A1D9B042B00D4039D; remoteInfo = "RCTImage-tvOS"; }; E99BBAD51EE4203500915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAD01EE4203500915720 /* RCTLinking.xcodeproj */; proxyType = 2; remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTLinking; }; E99BBAD71EE4203500915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAD01EE4203500915720 /* RCTLinking.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A28471D9B043800D4039D; remoteInfo = "RCTLinking-tvOS"; }; E99BBADE1EE4203B00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAD91EE4203B00915720 /* RCTNetwork.xcodeproj */; proxyType = 2; remoteGlobalIDString = 58B511DB1A9E6C8500147676; remoteInfo = RCTNetwork; }; E99BBAE01EE4203B00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAD91EE4203B00915720 /* RCTNetwork.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A28541D9B044C00D4039D; remoteInfo = "RCTNetwork-tvOS"; }; E99BBAE71EE4204700915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAE21EE4204700915720 /* RCTSettings.xcodeproj */; proxyType = 2; remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTSettings; }; E99BBAE91EE4204700915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAE21EE4204700915720 /* RCTSettings.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A28611D9B046600D4039D; remoteInfo = "RCTSettings-tvOS"; }; E99BBAF01EE4204D00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAEB1EE4204D00915720 /* RCTText.xcodeproj */; proxyType = 2; remoteGlobalIDString = 58B5119B1A9E6C1200147676; remoteInfo = RCTText; }; E99BBAF21EE4204D00915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAEB1EE4204D00915720 /* RCTText.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A287B1D9B048500D4039D; remoteInfo = "RCTText-tvOS"; }; E99BBAF81EE4205000915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAF41EE4205000915720 /* RCTVibration.xcodeproj */; proxyType = 2; remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; remoteInfo = RCTVibration; }; E99BBAFF1EE4205500915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAFA1EE4205400915720 /* RCTWebSocket.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3C86DF461ADF2C930047B81A; remoteInfo = RCTWebSocket; }; E99BBB011EE4205500915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBAFA1EE4205400915720 /* RCTWebSocket.xcodeproj */; proxyType = 2; remoteGlobalIDString = 2D2A28881D9B049200D4039D; remoteInfo = "RCTWebSocket-tvOS"; }; E99BBB071EE4205900915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBB031EE4205900915720 /* RCTWKWebView.xcodeproj */; proxyType = 2; remoteGlobalIDString = 0974579A1D2A440A000D9368; remoteInfo = RCTWKWebView; }; E99BBB191EE4207300915720 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E99BBB151EE4207200915720 /* ReactNativeNavigation.xcodeproj */; proxyType = 2; remoteGlobalIDString = D8AFADBD1BEE6F3F00A4592D; remoteInfo = ReactNativeNavigation; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ E91D41401EE4233F009BE67F /* web */ = {isa = PBXFileReference; lastKnownFileType = folder; name = web; path = ../web; sourceTree = ""; }; E91D41871EE4241F009BE67F /* NSURLProtocol+WKWebViewSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURLProtocol+WKWebViewSupport.h"; sourceTree = ""; }; E91D41881EE4241F009BE67F /* NSURLProtocol+WKWebViewSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURLProtocol+WKWebViewSupport.m"; sourceTree = ""; }; E91D41BF1EE42AD6009BE67F /* AppProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppProtocol.swift; sourceTree = ""; }; E99BB9EC1EE411AA00915720 /* Nabi.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Nabi.app; sourceTree = BUILT_PRODUCTS_DIR; }; E99BB9EF1EE411AA00915720 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E99BB9F61EE411AA00915720 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; E99BB9FB1EE411AA00915720 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E99BBA001EE411AA00915720 /* NabiTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NabiTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBA041EE411AA00915720 /* NabiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NabiTests.swift; sourceTree = ""; }; E99BBA061EE411AA00915720 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E99BBA0B1EE411AA00915720 /* NabiUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NabiUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBA0F1EE411AA00915720 /* NabiUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NabiUITests.swift; sourceTree = ""; }; E99BBA111EE411AA00915720 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E99BBA391EE4133900915720 /* Nabi-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Nabi-Bridging-Header.h"; sourceTree = ""; }; E99BBA3E1EE4135900915720 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; E99BBA971EE41FEA00915720 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; E99BBAB21EE4200A00915720 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; E99BBAB81EE4201E00915720 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; E99BBAC11EE4202500915720 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; E99BBAC71EE4202B00915720 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; E99BBAD01EE4203500915720 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; E99BBAD91EE4203B00915720 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; E99BBAE21EE4204700915720 /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; E99BBAEB1EE4204D00915720 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; E99BBAF41EE4205000915720 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; E99BBAFA1EE4205400915720 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; E99BBB031EE4205900915720 /* RCTWKWebView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWKWebView.xcodeproj; path = "../node_modules/react-native-wkwebview-reborn/ios/RCTWKWebView.xcodeproj"; sourceTree = ""; }; E99BBB151EE4207200915720 /* ReactNativeNavigation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactNativeNavigation.xcodeproj; path = "../node_modules/react-native-navigation/ios/ReactNativeNavigation.xcodeproj"; sourceTree = ""; }; E99BBB7C1EE4227100915720 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ E99BB9E91EE411AA00915720 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( E99BBA3F1EE4135900915720 /* WebKit.framework in Frameworks */, E99BBB301EE420A600915720 /* libReact.a in Frameworks */, E99BBB511EE420B100915720 /* libRCTActionSheet.a in Frameworks */, E99BBB521EE420B600915720 /* libRCTAnimation.a in Frameworks */, E99BBB531EE420BC00915720 /* libRCTGeolocation.a in Frameworks */, E99BBB541EE420C200915720 /* libRCTImage.a in Frameworks */, E99BBB551EE420C700915720 /* libRCTLinking.a in Frameworks */, E99BBB561EE420D400915720 /* libRCTNetwork.a in Frameworks */, E99BBB571EE420D800915720 /* libRCTSettings.a in Frameworks */, E99BBB581EE420DF00915720 /* libRCTText.a in Frameworks */, E99BBB591EE420E400915720 /* libRCTVibration.a in Frameworks */, E99BBB5A1EE420E900915720 /* libRCTWebSocket.a in Frameworks */, E99BBB5B1EE420F400915720 /* libRCTWKWebView.a in Frameworks */, E99BBB5C1EE420FB00915720 /* libReactNativeNavigation.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; E99BB9FD1EE411AA00915720 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; E99BBA081EE411AA00915720 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ E91D41851EE4241F009BE67F /* Vendor */ = { isa = PBXGroup; children = ( E91D41861EE4241F009BE67F /* WKWebViewWithURLProtocol */, ); path = Vendor; sourceTree = ""; }; E91D41861EE4241F009BE67F /* WKWebViewWithURLProtocol */ = { isa = PBXGroup; children = ( E91D41871EE4241F009BE67F /* NSURLProtocol+WKWebViewSupport.h */, E91D41881EE4241F009BE67F /* NSURLProtocol+WKWebViewSupport.m */, ); path = WKWebViewWithURLProtocol; sourceTree = ""; }; E99BB9E31EE411AA00915720 = { isa = PBXGroup; children = ( E99BB9EE1EE411AA00915720 /* Nabi */, E91D41401EE4233F009BE67F /* web */, E91D41851EE4241F009BE67F /* Vendor */, E99BBA031EE411AA00915720 /* NabiTests */, E99BBA0E1EE411AA00915720 /* NabiUITests */, E99BBA961EE41FCC00915720 /* Libraries */, E99BB9ED1EE411AA00915720 /* Products */, E99BBA3D1EE4135900915720 /* Frameworks */, ); sourceTree = ""; }; E99BB9ED1EE411AA00915720 /* Products */ = { isa = PBXGroup; children = ( E99BB9EC1EE411AA00915720 /* Nabi.app */, E99BBA001EE411AA00915720 /* NabiTests.xctest */, E99BBA0B1EE411AA00915720 /* NabiUITests.xctest */, ); name = Products; sourceTree = ""; }; E99BB9EE1EE411AA00915720 /* Nabi */ = { isa = PBXGroup; children = ( E99BB9EF1EE411AA00915720 /* AppDelegate.swift */, E91D41BF1EE42AD6009BE67F /* AppProtocol.swift */, E99BB9F61EE411AA00915720 /* Assets.xcassets */, E99BBB7B1EE4227100915720 /* LaunchScreen.xib */, E99BB9FB1EE411AA00915720 /* Info.plist */, E99BBA391EE4133900915720 /* Nabi-Bridging-Header.h */, ); path = Nabi; sourceTree = ""; }; E99BBA031EE411AA00915720 /* NabiTests */ = { isa = PBXGroup; children = ( E99BBA041EE411AA00915720 /* NabiTests.swift */, E99BBA061EE411AA00915720 /* Info.plist */, ); path = NabiTests; sourceTree = ""; }; E99BBA0E1EE411AA00915720 /* NabiUITests */ = { isa = PBXGroup; children = ( E99BBA0F1EE411AA00915720 /* NabiUITests.swift */, E99BBA111EE411AA00915720 /* Info.plist */, ); path = NabiUITests; sourceTree = ""; }; E99BBA3D1EE4135900915720 /* Frameworks */ = { isa = PBXGroup; children = ( E99BBA3E1EE4135900915720 /* WebKit.framework */, ); name = Frameworks; sourceTree = ""; }; E99BBA961EE41FCC00915720 /* Libraries */ = { isa = PBXGroup; children = ( E99BBA971EE41FEA00915720 /* React.xcodeproj */, E99BBAB21EE4200A00915720 /* RCTActionSheet.xcodeproj */, E99BBAB81EE4201E00915720 /* RCTAnimation.xcodeproj */, E99BBAC11EE4202500915720 /* RCTGeolocation.xcodeproj */, E99BBAC71EE4202B00915720 /* RCTImage.xcodeproj */, E99BBAD01EE4203500915720 /* RCTLinking.xcodeproj */, E99BBAD91EE4203B00915720 /* RCTNetwork.xcodeproj */, E99BBAE21EE4204700915720 /* RCTSettings.xcodeproj */, E99BBAEB1EE4204D00915720 /* RCTText.xcodeproj */, E99BBAF41EE4205000915720 /* RCTVibration.xcodeproj */, E99BBAFA1EE4205400915720 /* RCTWebSocket.xcodeproj */, E99BBB031EE4205900915720 /* RCTWKWebView.xcodeproj */, E99BBB151EE4207200915720 /* ReactNativeNavigation.xcodeproj */, ); name = Libraries; sourceTree = ""; }; E99BBA981EE41FEA00915720 /* Products */ = { isa = PBXGroup; children = ( E99BBAA31EE41FEA00915720 /* libReact.a */, E99BBAA51EE41FEA00915720 /* libReact.a */, E99BBAA71EE41FEA00915720 /* libyoga.a */, E99BBAA91EE41FEA00915720 /* libyoga.a */, E99BBAAB1EE41FEA00915720 /* libcxxreact.a */, E99BBAAD1EE41FEA00915720 /* libcxxreact.a */, E99BBAAF1EE41FEA00915720 /* libjschelpers.a */, E99BBAB11EE41FEA00915720 /* libjschelpers.a */, ); name = Products; sourceTree = ""; }; E99BBAB31EE4200A00915720 /* Products */ = { isa = PBXGroup; children = ( E99BBAB71EE4200A00915720 /* libRCTActionSheet.a */, ); name = Products; sourceTree = ""; }; E99BBAB91EE4201E00915720 /* Products */ = { isa = PBXGroup; children = ( E99BBABE1EE4201E00915720 /* libRCTAnimation.a */, E99BBAC01EE4201E00915720 /* libRCTAnimation.a */, ); name = Products; sourceTree = ""; }; E99BBAC21EE4202500915720 /* Products */ = { isa = PBXGroup; children = ( E99BBAC61EE4202500915720 /* libRCTGeolocation.a */, ); name = Products; sourceTree = ""; }; E99BBAC81EE4202B00915720 /* Products */ = { isa = PBXGroup; children = ( E99BBACD1EE4202B00915720 /* libRCTImage.a */, E99BBACF1EE4202B00915720 /* libRCTImage-tvOS.a */, ); name = Products; sourceTree = ""; }; E99BBAD11EE4203500915720 /* Products */ = { isa = PBXGroup; children = ( E99BBAD61EE4203500915720 /* libRCTLinking.a */, E99BBAD81EE4203500915720 /* libRCTLinking-tvOS.a */, ); name = Products; sourceTree = ""; }; E99BBADA1EE4203B00915720 /* Products */ = { isa = PBXGroup; children = ( E99BBADF1EE4203B00915720 /* libRCTNetwork.a */, E99BBAE11EE4203B00915720 /* libRCTNetwork-tvOS.a */, ); name = Products; sourceTree = ""; }; E99BBAE31EE4204700915720 /* Products */ = { isa = PBXGroup; children = ( E99BBAE81EE4204700915720 /* libRCTSettings.a */, E99BBAEA1EE4204700915720 /* libRCTSettings-tvOS.a */, ); name = Products; sourceTree = ""; }; E99BBAEC1EE4204D00915720 /* Products */ = { isa = PBXGroup; children = ( E99BBAF11EE4204D00915720 /* libRCTText.a */, E99BBAF31EE4204D00915720 /* libRCTText-tvOS.a */, ); name = Products; sourceTree = ""; }; E99BBAF51EE4205000915720 /* Products */ = { isa = PBXGroup; children = ( E99BBAF91EE4205000915720 /* libRCTVibration.a */, ); name = Products; sourceTree = ""; }; E99BBAFB1EE4205400915720 /* Products */ = { isa = PBXGroup; children = ( E99BBB001EE4205500915720 /* libRCTWebSocket.a */, E99BBB021EE4205500915720 /* libRCTWebSocket-tvOS.a */, ); name = Products; sourceTree = ""; }; E99BBB041EE4205900915720 /* Products */ = { isa = PBXGroup; children = ( E99BBB081EE4205900915720 /* libRCTWKWebView.a */, ); name = Products; sourceTree = ""; }; E99BBB161EE4207200915720 /* Products */ = { isa = PBXGroup; children = ( E99BBB1A1EE4207300915720 /* libReactNativeNavigation.a */, ); name = Products; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ E99BB9EB1EE411AA00915720 /* Nabi */ = { isa = PBXNativeTarget; buildConfigurationList = E99BBA141EE411AA00915720 /* Build configuration list for PBXNativeTarget "Nabi" */; buildPhases = ( E99BB9E81EE411AA00915720 /* Sources */, E99BB9E91EE411AA00915720 /* Frameworks */, E99BB9EA1EE411AA00915720 /* Resources */, E99BBB5D1EE4210E00915720 /* Bundle React Native code and images */, ); buildRules = ( ); dependencies = ( ); name = Nabi; productName = Nabi; productReference = E99BB9EC1EE411AA00915720 /* Nabi.app */; productType = "com.apple.product-type.application"; }; E99BB9FF1EE411AA00915720 /* NabiTests */ = { isa = PBXNativeTarget; buildConfigurationList = E99BBA171EE411AA00915720 /* Build configuration list for PBXNativeTarget "NabiTests" */; buildPhases = ( E99BB9FC1EE411AA00915720 /* Sources */, E99BB9FD1EE411AA00915720 /* Frameworks */, E99BB9FE1EE411AA00915720 /* Resources */, ); buildRules = ( ); dependencies = ( E99BBA021EE411AA00915720 /* PBXTargetDependency */, ); name = NabiTests; productName = NabiTests; productReference = E99BBA001EE411AA00915720 /* NabiTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; E99BBA0A1EE411AA00915720 /* NabiUITests */ = { isa = PBXNativeTarget; buildConfigurationList = E99BBA1A1EE411AA00915720 /* Build configuration list for PBXNativeTarget "NabiUITests" */; buildPhases = ( E99BBA071EE411AA00915720 /* Sources */, E99BBA081EE411AA00915720 /* Frameworks */, E99BBA091EE411AA00915720 /* Resources */, ); buildRules = ( ); dependencies = ( E99BBA0D1EE411AA00915720 /* PBXTargetDependency */, ); name = NabiUITests; productName = NabiUITests; productReference = E99BBA0B1EE411AA00915720 /* NabiUITests.xctest */; productType = "com.apple.product-type.bundle.ui-testing"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ E99BB9E41EE411AA00915720 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0830; LastUpgradeCheck = 0830; ORGANIZATIONNAME = "Peter Jihoon Kim"; TargetAttributes = { E99BB9EB1EE411AA00915720 = { CreatedOnToolsVersion = 8.3.2; DevelopmentTeam = 3K6TZ9NCHM; LastSwiftMigration = 0830; ProvisioningStyle = Automatic; }; E99BB9FF1EE411AA00915720 = { CreatedOnToolsVersion = 8.3.2; DevelopmentTeam = 3K6TZ9NCHM; ProvisioningStyle = Automatic; TestTargetID = E99BB9EB1EE411AA00915720; }; E99BBA0A1EE411AA00915720 = { CreatedOnToolsVersion = 8.3.2; DevelopmentTeam = 3K6TZ9NCHM; ProvisioningStyle = Automatic; TestTargetID = E99BB9EB1EE411AA00915720; }; }; }; buildConfigurationList = E99BB9E71EE411AA00915720 /* Build configuration list for PBXProject "Nabi" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = E99BB9E31EE411AA00915720; productRefGroup = E99BB9ED1EE411AA00915720 /* Products */; projectDirPath = ""; projectReferences = ( { ProductGroup = E99BBAB31EE4200A00915720 /* Products */; ProjectRef = E99BBAB21EE4200A00915720 /* RCTActionSheet.xcodeproj */; }, { ProductGroup = E99BBAB91EE4201E00915720 /* Products */; ProjectRef = E99BBAB81EE4201E00915720 /* RCTAnimation.xcodeproj */; }, { ProductGroup = E99BBAC21EE4202500915720 /* Products */; ProjectRef = E99BBAC11EE4202500915720 /* RCTGeolocation.xcodeproj */; }, { ProductGroup = E99BBAC81EE4202B00915720 /* Products */; ProjectRef = E99BBAC71EE4202B00915720 /* RCTImage.xcodeproj */; }, { ProductGroup = E99BBAD11EE4203500915720 /* Products */; ProjectRef = E99BBAD01EE4203500915720 /* RCTLinking.xcodeproj */; }, { ProductGroup = E99BBADA1EE4203B00915720 /* Products */; ProjectRef = E99BBAD91EE4203B00915720 /* RCTNetwork.xcodeproj */; }, { ProductGroup = E99BBAE31EE4204700915720 /* Products */; ProjectRef = E99BBAE21EE4204700915720 /* RCTSettings.xcodeproj */; }, { ProductGroup = E99BBAEC1EE4204D00915720 /* Products */; ProjectRef = E99BBAEB1EE4204D00915720 /* RCTText.xcodeproj */; }, { ProductGroup = E99BBAF51EE4205000915720 /* Products */; ProjectRef = E99BBAF41EE4205000915720 /* RCTVibration.xcodeproj */; }, { ProductGroup = E99BBAFB1EE4205400915720 /* Products */; ProjectRef = E99BBAFA1EE4205400915720 /* RCTWebSocket.xcodeproj */; }, { ProductGroup = E99BBB041EE4205900915720 /* Products */; ProjectRef = E99BBB031EE4205900915720 /* RCTWKWebView.xcodeproj */; }, { ProductGroup = E99BBA981EE41FEA00915720 /* Products */; ProjectRef = E99BBA971EE41FEA00915720 /* React.xcodeproj */; }, { ProductGroup = E99BBB161EE4207200915720 /* Products */; ProjectRef = E99BBB151EE4207200915720 /* ReactNativeNavigation.xcodeproj */; }, ); projectRoot = ""; targets = ( E99BB9EB1EE411AA00915720 /* Nabi */, E99BB9FF1EE411AA00915720 /* NabiTests */, E99BBA0A1EE411AA00915720 /* NabiUITests */, ); }; /* End PBXProject section */ /* Begin PBXReferenceProxy section */ E99BBAA31EE41FEA00915720 /* libReact.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libReact.a; remoteRef = E99BBAA21EE41FEA00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAA51EE41FEA00915720 /* libReact.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libReact.a; remoteRef = E99BBAA41EE41FEA00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAA71EE41FEA00915720 /* libyoga.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libyoga.a; remoteRef = E99BBAA61EE41FEA00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAA91EE41FEA00915720 /* libyoga.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libyoga.a; remoteRef = E99BBAA81EE41FEA00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAAB1EE41FEA00915720 /* libcxxreact.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libcxxreact.a; remoteRef = E99BBAAA1EE41FEA00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAAD1EE41FEA00915720 /* libcxxreact.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libcxxreact.a; remoteRef = E99BBAAC1EE41FEA00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAAF1EE41FEA00915720 /* libjschelpers.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libjschelpers.a; remoteRef = E99BBAAE1EE41FEA00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAB11EE41FEA00915720 /* libjschelpers.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libjschelpers.a; remoteRef = E99BBAB01EE41FEA00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAB71EE4200A00915720 /* libRCTActionSheet.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTActionSheet.a; remoteRef = E99BBAB61EE4200A00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBABE1EE4201E00915720 /* libRCTAnimation.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTAnimation.a; remoteRef = E99BBABD1EE4201E00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAC01EE4201E00915720 /* libRCTAnimation.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTAnimation.a; remoteRef = E99BBABF1EE4201E00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAC61EE4202500915720 /* libRCTGeolocation.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTGeolocation.a; remoteRef = E99BBAC51EE4202500915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBACD1EE4202B00915720 /* libRCTImage.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTImage.a; remoteRef = E99BBACC1EE4202B00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBACF1EE4202B00915720 /* libRCTImage-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTImage-tvOS.a"; remoteRef = E99BBACE1EE4202B00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAD61EE4203500915720 /* libRCTLinking.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTLinking.a; remoteRef = E99BBAD51EE4203500915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAD81EE4203500915720 /* libRCTLinking-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTLinking-tvOS.a"; remoteRef = E99BBAD71EE4203500915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBADF1EE4203B00915720 /* libRCTNetwork.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTNetwork.a; remoteRef = E99BBADE1EE4203B00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAE11EE4203B00915720 /* libRCTNetwork-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTNetwork-tvOS.a"; remoteRef = E99BBAE01EE4203B00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAE81EE4204700915720 /* libRCTSettings.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTSettings.a; remoteRef = E99BBAE71EE4204700915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAEA1EE4204700915720 /* libRCTSettings-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTSettings-tvOS.a"; remoteRef = E99BBAE91EE4204700915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAF11EE4204D00915720 /* libRCTText.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTText.a; remoteRef = E99BBAF01EE4204D00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAF31EE4204D00915720 /* libRCTText-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTText-tvOS.a"; remoteRef = E99BBAF21EE4204D00915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBAF91EE4205000915720 /* libRCTVibration.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTVibration.a; remoteRef = E99BBAF81EE4205000915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBB001EE4205500915720 /* libRCTWebSocket.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTWebSocket.a; remoteRef = E99BBAFF1EE4205500915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBB021EE4205500915720 /* libRCTWebSocket-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = "libRCTWebSocket-tvOS.a"; remoteRef = E99BBB011EE4205500915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBB081EE4205900915720 /* libRCTWKWebView.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libRCTWKWebView.a; remoteRef = E99BBB071EE4205900915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; E99BBB1A1EE4207300915720 /* libReactNativeNavigation.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libReactNativeNavigation.a; remoteRef = E99BBB191EE4207300915720 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ E99BB9EA1EE411AA00915720 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( E91D41411EE4233F009BE67F /* web in Resources */, E99BBB7D1EE4227100915720 /* LaunchScreen.xib in Resources */, E99BB9F71EE411AA00915720 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; E99BB9FE1EE411AA00915720 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; E99BBA091EE411AA00915720 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ E99BBB5D1EE4210E00915720 /* Bundle React Native code and images */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 12; files = ( ); inputPaths = ( ); name = "Bundle React Native code and images"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ E99BB9E81EE411AA00915720 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( E91D41891EE4241F009BE67F /* NSURLProtocol+WKWebViewSupport.m in Sources */, E99BB9F01EE411AA00915720 /* AppDelegate.swift in Sources */, E91D41C01EE42AD6009BE67F /* AppProtocol.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; E99BB9FC1EE411AA00915720 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( E99BBA051EE411AA00915720 /* NabiTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; E99BBA071EE411AA00915720 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( E99BBA101EE411AA00915720 /* NabiUITests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ E99BBA021EE411AA00915720 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = E99BB9EB1EE411AA00915720 /* Nabi */; targetProxy = E99BBA011EE411AA00915720 /* PBXContainerItemProxy */; }; E99BBA0D1EE411AA00915720 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = E99BB9EB1EE411AA00915720 /* Nabi */; targetProxy = E99BBA0C1EE411AA00915720 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ E99BBB7B1EE4227100915720 /* LaunchScreen.xib */ = { isa = PBXVariantGroup; children = ( E99BBB7C1EE4227100915720 /* Base */, ); name = LaunchScreen.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ E99BBA121EE411AA00915720 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; E99BBA131EE411AA00915720 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; E99BBA151EE411AA00915720 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; DEVELOPMENT_TEAM = 3K6TZ9NCHM; INFOPLIST_FILE = Nabi/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); PRODUCT_BUNDLE_IDENTIFIER = cloud.kim.Nabi; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Nabi/Nabi-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0; USER_HEADER_SEARCH_PATHS = "$(inherited) $(SRCROOT)/../node_modules/react-native/React/** $(SRCROOT)/../node_modules/react-native-navigation/ios/**"; }; name = Debug; }; E99BBA161EE411AA00915720 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; DEVELOPMENT_TEAM = 3K6TZ9NCHM; INFOPLIST_FILE = Nabi/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); PRODUCT_BUNDLE_IDENTIFIER = cloud.kim.Nabi; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Nabi/Nabi-Bridging-Header.h"; SWIFT_VERSION = 3.0; USER_HEADER_SEARCH_PATHS = "$(inherited) $(SRCROOT)/../node_modules/react-native/React/** $(SRCROOT)/../node_modules/react-native-navigation/ios/**"; }; name = Release; }; E99BBA181EE411AA00915720 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = 3K6TZ9NCHM; INFOPLIST_FILE = NabiTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = cloud.kim.NabiTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Nabi.app/Nabi"; }; name = Debug; }; E99BBA191EE411AA00915720 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; DEVELOPMENT_TEAM = 3K6TZ9NCHM; INFOPLIST_FILE = NabiTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = cloud.kim.NabiTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Nabi.app/Nabi"; }; name = Release; }; E99BBA1B1EE411AA00915720 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; DEVELOPMENT_TEAM = 3K6TZ9NCHM; INFOPLIST_FILE = NabiUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = cloud.kim.NabiUITests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; TEST_TARGET_NAME = Nabi; }; name = Debug; }; E99BBA1C1EE411AA00915720 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; DEVELOPMENT_TEAM = 3K6TZ9NCHM; INFOPLIST_FILE = NabiUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = cloud.kim.NabiUITests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; TEST_TARGET_NAME = Nabi; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ E99BB9E71EE411AA00915720 /* Build configuration list for PBXProject "Nabi" */ = { isa = XCConfigurationList; buildConfigurations = ( E99BBA121EE411AA00915720 /* Debug */, E99BBA131EE411AA00915720 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; E99BBA141EE411AA00915720 /* Build configuration list for PBXNativeTarget "Nabi" */ = { isa = XCConfigurationList; buildConfigurations = ( E99BBA151EE411AA00915720 /* Debug */, E99BBA161EE411AA00915720 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; E99BBA171EE411AA00915720 /* Build configuration list for PBXNativeTarget "NabiTests" */ = { isa = XCConfigurationList; buildConfigurations = ( E99BBA181EE411AA00915720 /* Debug */, E99BBA191EE411AA00915720 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; E99BBA1A1EE411AA00915720 /* Build configuration list for PBXNativeTarget "NabiUITests" */ = { isa = XCConfigurationList; buildConfigurations = ( E99BBA1B1EE411AA00915720 /* Debug */, E99BBA1C1EE411AA00915720 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = E99BB9E41EE411AA00915720 /* Project object */; } ================================================ FILE: ios/Nabi.xcodeproj/xcshareddata/xcschemes/Nabi.xcscheme ================================================ ================================================ FILE: ios/NabiTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: ios/NabiTests/NabiTests.swift ================================================ // // NabiTests.swift // NabiTests // // Created by Peter Jihoon Kim on 6/4/17. // Copyright © 2017 Peter Jihoon Kim. All rights reserved. // import XCTest @testable import Nabi class NabiTests: XCTestCase { override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testExample() { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. } func testPerformanceExample() { // This is an example of a performance test case. self.measure { // Put the code you want to measure the time of here. } } } ================================================ FILE: ios/NabiUITests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: ios/NabiUITests/NabiUITests.swift ================================================ // // NabiUITests.swift // NabiUITests // // Created by Peter Jihoon Kim on 6/4/17. // Copyright © 2017 Peter Jihoon Kim. All rights reserved. // import XCTest class NabiUITests: XCTestCase { override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. // In UI tests it is usually best to stop immediately when a failure occurs. continueAfterFailure = false // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. XCUIApplication().launch() // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testExample() { // Use recording to get started writing UI tests. // Use XCTAssert and related functions to verify your tests produce the correct results. } } ================================================ FILE: ios/vendor/WKWebViewWithURLProtocol/NSURLProtocol+WKWebViewSupport.h ================================================ // // NSURLProtocol+WKWebViewSupport.h // Pods // // Created by Dylan on 2016/11/14. // // #import @interface NSURLProtocol (WKWebViewSupport) + (void)wk_registerScheme:(NSString *)scheme; + (void)wk_unregisterScheme:(NSString *)scheme; @end ================================================ FILE: ios/vendor/WKWebViewWithURLProtocol/NSURLProtocol+WKWebViewSupport.m ================================================ // // NSURLProtocol+WKWebViewSupport.m // Pods // // Created by Dylan on 2016/11/14. // // #import "NSURLProtocol+WKWebViewSupport.h" #import Class WK_ContextControllerClass() { static Class cls; if (!cls) { cls = [[[WKWebView new] valueForKey:@"browsingContextController"] class]; } return cls; } SEL WK_RegisterSchemeSelector() { return NSSelectorFromString(@"registerSchemeForCustomProtocol:"); } SEL WK_UnregisterSchemeSelector() { return NSSelectorFromString(@"unregisterSchemeForCustomProtocol:"); } @implementation NSURLProtocol (WKWebViewSupport) + (void)wk_registerScheme:(NSString *)scheme { Class cls = WK_ContextControllerClass(); SEL sel = WK_RegisterSchemeSelector(); if ([(id)cls respondsToSelector:sel]) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [(id)cls performSelector:sel withObject:scheme]; #pragma clang diagnostic pop } } + (void)wk_unregisterScheme:(NSString *)scheme { Class cls = WK_ContextControllerClass(); SEL sel = WK_UnregisterSchemeSelector(); if ([(id)cls respondsToSelector:sel]) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [(id)cls performSelector:sel withObject:scheme]; #pragma clang diagnostic pop } } @end ================================================ FILE: package.json ================================================ { "name": "MetaMaskMobile", "version": "0.0.1", "private": true, "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run-ios": "node node_modules/react-native/local-cli/cli.js run-ios", "run-android": "node node_modules/react-native/local-cli/cli.js run-android", "test": "jest", "tsc": "tsc --noEmit --pretty", "fmt": "prettier --no-semi --single-quote --jsx-single-quote --space-before-function-paren --write '*.js' 'src/**/*.{j,t}s{,x}'", "lint": "tslint -p . --type-check 'src/**/*.ts{,x}'", "watch": "nodemon -e ts,tsx,js,json --watch src/ --exec 'yarn lint && yarn tsc && yarn fmt'" }, "dependencies": { "node-libs-react-native": "petejkim/node-libs-react-native#8b5a3a9700a08f6a1d8f58819479bf4d4d589970", "react": "16.0.0-alpha.12", "react-native": "0.46.0", "react-native-navigation": "^1.1.134", "react-native-wkwebview-reborn": "petejkim/react-native-wkwebview#a38c83174bdf6a0b0edc6f3aa7acb8885e7c2d96" }, "devDependencies": { "@types/jest": "^20.0.2", "@types/node": "^8.0.9", "@types/react": "^15.0.35", "@types/react-native": "^0.44.18", "babel-jest": "20.0.3", "babel-preset-react-native": "2.0.0", "jest": "20.0.4", "nodemon": "^1.11.0", "prettier-miscellaneous": "^1.5.2-fix", "react-native-typescript-transformer": "1.1.2", "react-test-renderer": "16.0.0-alpha.12", "ts-jest": "^20.0.6", "tslint": "^5.4.3", "tslint-config-standard": "^6.0.1", "tslint-react": "^3.0.0", "typescript": "~2.4.1" }, "jest": { "preset": "react-native", "transform": { "^.+\\.jsx?$": "/node_modules/babel-jest", "^.+\\.tsx?$": "/node_modules/ts-jest/preprocessor.js" }, "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$", "moduleFileExtensions": [ "ts", "tsx", "js", "json" ] } } ================================================ FILE: rn-cli.config.js ================================================ const extraNodeModules = require('node-libs-react-native') module.exports = { extraNodeModules, getSourceExts () { return ['ts', 'tsx'] }, getTransformModulePath () { return require.resolve('react-native-typescript-transformer') } } ================================================ FILE: src/@types/react-native-navigation.d.ts ================================================ declare module 'react-native-navigation' { import { ComponentClass } from 'react' import { ComponentProvider } from 'react-native' export interface NavigatorEvent { type: string id: string } export class Navigator {} export type NavigatorEventHandler = (NavigatorEvent) => void interface DismissModalParams { animationType?: 'slide-down' | 'none' | 'slide-down' } interface ShowModalParams { screen: string title?: string passProps?: any navigatorStyle?: any navigatorButtons?: any animationType?: 'slide-up' | 'none' | 'slide-up' } interface StartSingleScreenAppParams { screen: { screen: string title?: string navigatorStyle?: any navigatorButtons?: any } drawer?: { left?: { screen: string passProps?: any } right?: { screen: string passProps?: any } disableOpenGesture?: boolean } passProps?: any animationType?: 'slide-down' | 'none' | 'slide-down' | 'fade' } export namespace Navigation { function registerComponent ( screenID: string, generator: ComponentProvider, store?: any, Provider?: ComponentClass ) function dismissModal (params: DismissModalParams = {}) function showModal (params: ShowModalParams = {}) function setOnNavigatorEvent (callback: NavigatorEventHandler) function startSingleScreenApp (params: StartSingleScreenAppParams) } } ================================================ FILE: src/@types/react-native-wkwebview-reborn.d.ts ================================================ declare module 'react-native-wkwebview-reborn' { import { Component } from 'react' import { EdgeInsetsPropType, NativeSyntheticEvent, ViewStyleProp } from 'react-native' export interface WKWebViewMessage { body: any name: string target: number } export interface WKWebViewBaseEvent { url: string loading: boolean title: string canGoBack: boolean canGoForward: boolean } export interface WKWebViewProps { html?: string url?: string source?: | { uri: string method?: string headers?: { [string]: string } body?: string } | { html: string baseUrl: string } | number renderError?: (errorDomain, errorCode, errorDesc) => void renderLoading?: () => void onLoad?: (event: NativeSyntheticEvent) => void onLoadEnd?: (event: NativeSyntheticEvent) => void onLoadStart?: (event: NativeSyntheticEvent) => void onError?: (event: NativeSyntheticEvent) => void onProgress?: (progress: number) => void onMessage?: (msg: WKWebViewMessage) => void bounces?: boolean scrollEnabled?: boolean allowsBackForwardNavigationGestures?: boolean automaticallyAdjustContentInsets?: boolean contentInset?: EdgeInsetsPropType onNavigationStateChange?: (event: any) => void scalesPageToFit?: boolean startInLoadingState?: boolean style?: ViewStyleProp injectedJavaScript?: string runJavaScriptAtDocumentStart?: string runJavaScriptAtDocumentEnd?: string runJavaScriptInMainFrameOnly?: boolean onShouldStartLoadWithRequest?: (event: any) => boolean sendCookies?: boolean openNewWindowInWebView?: boolean hideKeyboardAccessoryView?: boolean customUserAgent?: string userAgent?: string pagingEnabled?: boolean } class WKWebView extends Component { goBack (): void goForward (): void reload (): void stopLoading (): void evaluateJavaScript (js: string): any getWebViewHandle (): any } export default WKWebView } ================================================ FILE: src/components/BrowserWindow.tsx ================================================ import React, { Component } from 'react' import { Image, StatusBar, StyleSheet, TouchableOpacity, View } from 'react-native' import WKWebView, { WKWebViewMessage } from 'react-native-wkwebview-reborn' import LocationBar from './LocationBar' import PageLoadProgress from './PageLoadProgress' import injection from '../injections/contentScript' import { sharedIPC as ipc } from '../ipc' import { TOOLBAR_HEIGHT, TOOLBAR_ICON_SIZE, TOOLBAR_PADDING, STATUS_BAR_HEIGHT } from '../constants' const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'stretch' }, navigateButton: { width: 24, height: 24, marginRight: TOOLBAR_PADDING }, metaMaskButton: { width: TOOLBAR_ICON_SIZE, height: TOOLBAR_ICON_SIZE }, disabledButton: { opacity: 0.25 }, toolbar: { paddingTop: STATUS_BAR_HEIGHT, paddingLeft: TOOLBAR_PADDING, paddingRight: TOOLBAR_PADDING, height: TOOLBAR_HEIGHT + STATUS_BAR_HEIGHT, backgroundColor: '#f2f2f2', borderBottomWidth: StyleSheet.hairlineWidth, borderBottomColor: '#b2b0b2', flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-end' }, webview: { flex: 1 } }) const injectedJavaScript = ` (${injection.toString()})(window, document) ` export interface Props { onPressMetaMaskButton: () => void } interface State { sourceUrl: string showProgress: boolean progress: number canGoBack: boolean canGoForward: boolean } export default class BrowserWindow extends Component { state = { sourceUrl: 'about:blank', showProgress: false, progress: 1, canGoBack: false, canGoForward: false } refs: { webview: WKWebView } connections: { [id: string]: boolean } = {} componentWillUnmount () { Object.keys(this.connections).forEach(function (id) { ipc.disconnect(id) }) } handlePressMetaMaskButton = (): void => { const { onPressMetaMaskButton } = this.props if (onPressMetaMaskButton) { onPressMetaMaskButton() } } handlePressBackButton = (): void => { this.refs.webview.goBack() } handlePressForwardButton = (): void => { this.refs.webview.goForward() } handleNavigate = (urlString: string): void => { const { sourceUrl } = this.state if (sourceUrl === urlString) { this.refs.webview.reload() return } this.setState({ sourceUrl: urlString }) } handleProgress = (progress: number): void => { this.setState({ progress }) } handleLoadStart = ({ nativeEvent: event }): void => { const url = event.url const changes = { sourceUrl: url, canGoBack: event.canGoBack, canGoForward: event.canGoForward } if (!url.startsWith('about:')) { Object.assign(changes, { showProgress: true, progress: 0 }) } this.setState(changes) } handleLoadEnd = ({ nativeEvent: event }): void => { this.setState({ canGoBack: event.canGoBack, canGoForward: event.canGoForward, showProgress: false, progress: 1 }) } handleMessage = (msg: WKWebViewMessage): void => { console.log('browser window message received', msg) const body = msg.body switch (body.action) { case 'connect': ipc.connect(body.name, body.id, body.url, this.refs.webview) this.connections[body.id] = true return case 'disconnect': ipc.disconnect(body.id) delete this.connections[body.id] return case 'message': ipc.sendToBackground(body.id, body.data) } } render () { const { sourceUrl, showProgress, progress, canGoBack, canGoForward } = this.state return ( {canGoBack ? : } {canGoForward ? : } ) } } ================================================ FILE: src/components/LocationBar.tsx ================================================ import React, { Component } from 'react' import { StyleSheet, TextInput, View } from 'react-native' import { normalizeUrl } from '../util' import { TOOLBAR_HEIGHT, TOOLBAR_PADDING, COLOR_HIGHLIGHT_BLUE } from '../constants' const styles = StyleSheet.create({ container: { flex: 1, height: TOOLBAR_HEIGHT - TOOLBAR_PADDING * 2, backgroundColor: 'white', marginRight: TOOLBAR_PADDING, borderWidth: StyleSheet.hairlineWidth, borderColor: '#b2b0b2', padding: StyleSheet.hairlineWidth, borderRadius: 4, justifyContent: 'center' }, containerFocused: { borderColor: COLOR_HIGHLIGHT_BLUE, borderWidth: 1, padding: 0 }, textInput: { width: '100%', height: '100%', paddingLeft: TOOLBAR_PADDING, fontSize: 15 } }) export interface Props { currentUrl: string onNavigate?: (url: string) => void } interface State { focused: boolean urlString: string } export default class LocationBar extends Component { state = { focused: false, urlString: this.props.currentUrl } componentWillReceiveProps (newProps: Props) { const { currentUrl } = this.props const { currentUrl: newCurrentLocation } = newProps const { focused } = this.state if (currentUrl !== newCurrentLocation && !focused) { this.setState({ urlString: newCurrentLocation }) } } handleFocus = (): void => { this.setState({ focused: true }) } handleBlur = (): void => { this.setState({ focused: false }) } handleChangeText = (text: string): void => { this.setState({ urlString: text }) } handleSubmitEditing = (): void => { const { onNavigate } = this.props const { urlString } = this.state if (typeof onNavigate === 'function') { onNavigate(normalizeUrl(urlString)) } } render () { const { focused, urlString } = this.state return ( ) } } ================================================ FILE: src/components/MetaMaskBackground.tsx ================================================ import React, { Component } from 'react' import { View } from 'react-native' import WKWebView, { WKWebViewMessage } from 'react-native-wkwebview-reborn' import injection from '../injections/metaMaskBackground' import { sharedIPC as ipc } from '../ipc' const manifest = require('../../web/metamask/manifest.json') const injectedJavaScript = ` (${injection.toString()})(window, document, ${JSON.stringify(manifest)}) ` export interface Props { onOpenMetaMask: () => void } export default class MetaMaskBackground extends Component { refs: { webview: WKWebView } componentDidMount () { ipc.setBackground(this.refs.webview) } handleMessage = (msg: WKWebViewMessage): void => { console.log('background message received', msg) const { body } = msg const action: string = body.action switch (action) { case 'message': ipc.sendToClient(body.id, body.data) return case 'metamask': const { onOpenMetaMask } = this.props if (onOpenMetaMask) { onOpenMetaMask() } } } render () { return ( ) } } ================================================ FILE: src/components/PageLoadProgress.tsx ================================================ import React, { Component } from 'react' import { Animated, StyleSheet, View } from 'react-native' import { COLOR_HIGHLIGHT_BLUE } from '../constants' const styles = StyleSheet.create({ container: { marginTop: -2, zIndex: 1 }, bar: { height: 2, backgroundColor: COLOR_HIGHLIGHT_BLUE, shadowColor: COLOR_HIGHLIGHT_BLUE } }) export interface Props { progress: number hidden: boolean } interface State { progressAnimated: Animated.Value opacityAnimated: Animated.Value } export default class PageLoadProgress extends Component { state = { progressAnimated: new Animated.Value(0), opacityAnimated: new Animated.Value(0) } componentWillReceiveProps (newProps: Props) { const { progress, hidden } = this.props const { progress: newProgress, hidden: newHidden } = newProps if ((!hidden || progress !== 1) && (newHidden || newProgress === 1)) { Animated.timing(this.state.progressAnimated, { toValue: 1, duration: 500 }).start() Animated.timing(this.state.opacityAnimated, { toValue: 0, delay: 500, duration: 200 }).start() return } if (newProgress !== progress) { if (newProgress <= 0.1) { this.state.progressAnimated.setValue(0) this.state.opacityAnimated.setValue(1) } Animated.timing(this.state.progressAnimated, { toValue: newProgress, duration: 500 }).start() } } render () { const { progressAnimated, opacityAnimated } = this.state return ( ) } } ================================================ FILE: src/constants.ts ================================================ import { Platform } from 'react-native' export const TOOLBAR_HEIGHT = Platform.OS === 'ios' ? 44 : 56 export const TOOLBAR_ICON_SIZE = Platform.OS === 'ios' ? 32 : 24 export const TOOLBAR_PADDING = Platform.OS === 'ios' ? 8 : 16 export const STATUS_BAR_HEIGHT = Platform.OS === 'ios' ? 20 : 0 export const COLOR_HIGHLIGHT_BLUE = '#3378f6' ================================================ FILE: src/index.ts ================================================ import { Navigation } from 'react-native-navigation' import { registerScreens } from './screens' export const startApp = function (): void { registerScreens() Navigation.startSingleScreenApp({ screen: { screen: 'nabi.RootScreen', navigatorStyle: { navBarHidden: true } } }) } ================================================ FILE: src/injections/contentScript.ts ================================================ import { PortListener, Port, MessageEvent } from './types' declare global { interface Window { webkit: { messageHandlers: { reactNative: { postMessage: (message: any) => void } } } browser: any } } export default function injectContentScript ( window: Window, document: Document ) { const uint8ArrayToHex = function (arr) { const hex = '0123456789abcdef' return Array.from(arr) .map((v: number) => hex[Math.floor(v / 16)] + hex[v % 16]) .join('') } const makePort = function (name, id): Port { return { name, id, onDisconnect: { addListener (_listener: PortListener): void {} }, onMessage: { addListener (listener: PortListener): void { window.addEventListener( 'port:message', function (evt: MessageEvent) { if (evt.detail.id === id) { listener(evt.detail.data) } }, false ) } }, postMessage (message: any): void { window.webkit.messageHandlers.reactNative.postMessage({ action: 'message', data: message, id }) } } } window.browser = { extension: { getURL (path: string) { return `about://metamask/${path}` } }, runtime: { connect ({ name }: { name: string }): Port { const id = uint8ArrayToHex( window.crypto.getRandomValues(new Uint8Array(8)) ) window.setTimeout(function () { window.webkit.messageHandlers.reactNative.postMessage({ action: 'connect', url: location.href, name, id }) window.addEventListener( 'pagehide', function () { window.webkit.messageHandlers.reactNative.postMessage({ action: 'disconnect', id }) }, false ) }, 1) return makePort(name, id) } } } const script = document.createElement('script') script.src = 'about://metamask/scripts/contentscript.js' script.onload = function () { if (this && this.parentNode) { this.parentNode.removeChild(this) } } const el = document.head || document.body || document.documentElement if (el) { el.appendChild(script) } } ================================================ FILE: src/injections/metaMaskBackground.ts ================================================ import { PortListener, Port, ConnectEvent } from './types' export default function bootstrapMetaMaskBackground ( window: Window, document: Document, manifest: {} ) { const makePort = function (name: string, id: string, url: string): Port { let disconnectListeners: PortListener[] = [] let messageListeners: PortListener[] = [] const messageHandler = function (evt: CustomEvent): void { if (evt.detail.id === id) { console.log('message received', evt) messageListeners.forEach(function (listener) { listener(evt.detail.data) }) } } const disconnectHandler = function (evt: CustomEvent): void { if (evt.detail.id === id) { console.log('disconnect', evt.detail) disconnectListeners.forEach(function (listener) { listener(evt.detail.data) }) window.removeEventListener('port:disconnect', disconnectHandler, false) window.removeEventListener('port:message', messageHandler, false) disconnectListeners = [] messageListeners = [] } } window.addEventListener('port:disconnect', disconnectHandler, false) window.addEventListener('port:message', messageHandler, false) return { name, sender: { url }, onDisconnect: { addListener (listener: PortListener): void { disconnectListeners.push(listener) } }, onMessage: { addListener (listener: PortListener): void { messageListeners.push(listener) } }, postMessage (message: any): void { console.log(`sending message back to ${name} ${id}: `, message) window.webkit.messageHandlers.reactNative.postMessage({ action: 'message', data: message, id }) } } } window.browser = { browserAction: { setBadgeText ({ text }: { text: string }): void { console.log('setBadgeText:', text) }, setBadgeBackgroundColor ({ color }: { color: string }): void { console.log('setBadgeBackgroundColor:', color) } }, runtime: { onConnect: { addListener (listener: PortListener): void { window.addEventListener( 'port:connect', function (evt: ConnectEvent) { console.log( 'connecting to port: ', evt.detail.name, evt.detail.id, evt.detail.url ) listener(makePort(evt.detail.name, evt.detail.id, evt.detail.url)) }, false ) } }, onInstalled: { addListener (_listener: PortListener): void {} }, getManifest (): {} { return manifest }, reload () {} }, tabs: { create ({ url: _url }) {} }, windows: { create ({ url }, cb) { if (url === 'notification.html') { window.webkit.messageHandlers.reactNative.postMessage({ action: 'metamask' }) if (typeof cb === 'function') cb() } }, update () {}, remove () {}, getAll (_, cb) { cb([]) } } } const script = document.createElement('script') script.src = '/scripts/background.js' script.onload = function () { if (this && this.parentNode) { this.parentNode.removeChild(this) } } if (document.body) { document.body.appendChild(script) } } ================================================ FILE: src/injections/metaMaskPopup.ts ================================================ import { PortListener, Port, MessageEvent } from './types' const bootstrapMetaMaskPopup = function ( window: Window, document: Document, manifest: {} ) { const uint8ArrayToHex = function (arr) { const hex = '0123456789abcdef' return Array.from(arr) .map((v: number) => hex[Math.floor(v / 16)] + hex[v % 16]) .join('') } const makePort = function (name, id): Port { return { name, id, onDisconnect: { addListener (_listener: PortListener): void {} }, onMessage: { addListener (listener: PortListener): void { window.addEventListener( 'port:message', function (evt: MessageEvent) { if (evt.detail.id === id) { listener(evt.detail.data) } }, false ) } }, postMessage (message: any): void { window.webkit.messageHandlers.reactNative.postMessage({ action: 'message', data: message, id }) } } } window.browser = { runtime: { connect ({ name }: { name: string }): Port { const id = uint8ArrayToHex( window.crypto.getRandomValues(new Uint8Array(8)) ) window.setTimeout(function () { window.webkit.messageHandlers.reactNative.postMessage({ action: 'connect', url: location.href, name, id }) window.addEventListener( 'pagehide', function () { window.webkit.messageHandlers.reactNative.postMessage({ action: 'disconnect', id }) }, false ) }, 1) return makePort(name, id) }, getManifest (): {} { return manifest } } } const script = document.createElement('script') script.src = '/scripts/popup.js' script.onload = function () { if (this && this.parentNode) { this.parentNode.removeChild(this) } } if (document.body) { document.body.appendChild(script) } } export default bootstrapMetaMaskPopup ================================================ FILE: src/injections/types.ts ================================================ export type PortListener = (data: any) => void export interface Port { id?: string name: string sender?: { url: string } onDisconnect: { addListener: (listener: PortListener) => void } onMessage: { addListener: (listener: PortListener) => void } postMessage: (message: any) => void } export interface ConnectEvent extends Event { detail: { id: string name: string url: string } } export interface MessageEvent extends Event { detail: { id: string data: any } } ================================================ FILE: src/ipc.ts ================================================ import WKWebView from 'react-native-wkwebview-reborn' class IPC { private background?: WKWebView private clients: { [id: string]: WKWebView } = {} setBackground (background: WKWebView): void { this.background = background } connect (name: string, id: string, url: string, client: WKWebView): void { console.log('connected:', name, id) this.clients[id] = client console.log(name) console.log(id) console.log(url) const detail = JSON.stringify({ name, id, url }) if (!this.background) throw new Error('ipc: background needs to be set') this.background.evaluateJavaScript(` window.dispatchEvent(new CustomEvent('port:connect', { detail: ${detail} })) `) } disconnect (id: string): void { console.log('disconnected:', id) if (!this.clients[id]) return delete this.clients[id] const detail = JSON.stringify({ id }) if (!this.background) throw new Error('ipc: background needs to be set') this.background.evaluateJavaScript(` window.dispatchEvent(new CustomEvent('port:disconnect', { detail: ${detail} })) `) } sendToBackground (id: string, data: any): void { console.log(`${id} sending message to background:`, data) const detail = JSON.stringify({ id, data }) if (!this.background) throw new Error('ipc: background needs to be set') this.background.evaluateJavaScript(` window.dispatchEvent(new CustomEvent('port:message', { detail: ${detail} })) `) } sendToClient (id: string, data: any): void { console.log(`background sending message to ${id}:`, data) const client = this.clients[id] if (!client) return const detail = JSON.stringify({ id, data }) client.evaluateJavaScript(` window.dispatchEvent(new CustomEvent('port:message', { detail: ${detail} })) `) } } export default IPC export const sharedIPC = new IPC() ================================================ FILE: src/screens/MetaMaskScreen.tsx ================================================ import React, { Component } from 'react' import { StyleSheet, View } from 'react-native' import { Navigation } from 'react-native-navigation' import WKWebView, { WKWebViewMessage } from 'react-native-wkwebview-reborn' import injection from '../injections/metaMaskPopup' import { sharedIPC as ipc } from '../ipc' const manifest = require('../../web/metamask/manifest.json') const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f7f7f7', justifyContent: 'center', alignItems: 'stretch' }, webview: { flex: 1, backgroundColor: '#f7f7f7' } }) const injectedJavaScript = ` (${injection.toString()})(window, document, ${JSON.stringify(manifest)}) ` export interface Props { navigator: any } export default class MetaMaskScreen extends Component { static navigatorButtons = { rightButtons: [ { title: 'Close', id: 'close' } ] } refs: { webview: WKWebView } connections: { [id: string]: boolean } = {} componentDidMount () { const { navigator } = this.props navigator.setOnNavigatorEvent(this.handleNavigatorEvent) } componentWillUnmount () { Object.keys(this.connections).forEach(function (id) { ipc.disconnect(id) }) } handleNavigatorEvent = event => { if (event.type === 'NavBarButtonPress' && event.id === 'close') { Navigation.dismissModal({}) } } handleMessage = (msg: WKWebViewMessage): void => { console.log('popup message received', msg) const body = msg.body switch (body.action) { case 'connect': ipc.connect(body.name, body.id, body.url, this.refs.webview) this.connections[body.id] = true return case 'disconnect': ipc.disconnect(body.id) delete this.connections[body.id] return case 'message': ipc.sendToBackground(body.id, body.data) } } render () { return ( ) } } ================================================ FILE: src/screens/RootScreen.tsx ================================================ import React, { Component } from 'react' import { StyleSheet, View } from 'react-native' import { Navigation } from 'react-native-navigation' import BrowserWindow from '../components/BrowserWindow' import MetaMaskBackground from '../components/MetaMaskBackground' const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', justifyContent: 'flex-start', alignItems: 'stretch' } }) export default class RootScreen extends Component { openMetaMask (): void { Navigation.showModal({ screen: 'nabi.MetaMaskScreen' }) } render () { return ( ) } } ================================================ FILE: src/screens/index.ts ================================================ import { Navigation } from 'react-native-navigation' import RootScreen from './RootScreen' import MetaMaskScreen from './MetaMaskScreen' export const registerScreens = function (): void { Navigation.registerComponent('nabi.RootScreen', () => RootScreen) Navigation.registerComponent('nabi.MetaMaskScreen', () => MetaMaskScreen) } ================================================ FILE: src/util.test.ts ================================================ import { normalizeUrl } from './util' describe('normalizeUrl', () => { it('can normalize urls that are missing protocols', () => { expect(normalizeUrl('example.com')).toEqual('http://example.com/') expect(normalizeUrl('example.com/foo/bar')).toEqual( 'http://example.com/foo/bar' ) expect(normalizeUrl('example.com:8080')).toEqual('http://example.com:8080/') expect(normalizeUrl('example.com:8080/foo/bar')).toEqual( 'http://example.com:8080/foo/bar' ) expect(normalizeUrl('about:blank')).toEqual('about:blank') }) }) ================================================ FILE: src/util.ts ================================================ import url from 'url' export const normalizeUrl = function (urlString: string): string { const u = url.parse(urlString) if ( u.protocol && !['http:', 'https:'].includes(u.protocol) && !u.slashes && !u.port && u.host && !Number.isNaN(parseInt(u.host, 10)) ) { u.port = u.host u.hostname = u.protocol.slice(0, -1) if (u.hostname && u.port) { u.host = `${u.hostname}:${u.port}` } u.protocol = 'http:' if (!u.pathname) { u.pathname = '/' u.path = undefined } } else if (!u.protocol) { u.host = undefined u.protocol = 'http:' const pathname = u.pathname if (pathname) { const slashIndex = pathname.indexOf('/') if (slashIndex !== -1) { u.host = pathname.slice(0, slashIndex) u.pathname = pathname.slice(slashIndex) } else { u.host = pathname u.pathname = '/' } u.path = undefined } } if (!u.slashes && u.protocol !== 'about:') { u.slashes = true } return url.format(u) } ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "target": "es2015", "module": "es2015", "moduleResolution": "node", "jsx": "react-native", "skipLibCheck": true, "allowSyntheticDefaultImports": true, "strictNullChecks": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "experimentalDecorators": true, "lib": [ "es7", "dom" ] }, "filesGlob": [ "src/**/*.ts", "src/**/*.tsx" ], "ignore": [ "android", "build", "ios", "node_modules" ], "types": [ "jest" ] } ================================================ FILE: tslint.json ================================================ { "extends": ["tslint-config-standard", "tslint-react"], "rules": { "jsx-alignment": false, "jsx-boolean-value": [true, "never"], "jsx-no-multiline-js": false, "jsx-wrap-multiline": false, "no-empty": false, "no-unused-variable": false, "semicolon": false, "ter-indent": false } } ================================================ FILE: web/metamask/_locales/en/messages.json ================================================ { "appName": { "message": "MetaMask", "description": "The name of the application" }, "appDescription": { "message": "Ethereum Identity Management", "description": "The description of the application" } } ================================================ FILE: web/metamask/_locales/es/messages.json ================================================ { "appName": { "message": "MetaMask", "description": "The name of the application" }, "appDescription": { "message": "Administración de identidad en Ethereum", "description": "The description of the application" } } ================================================ FILE: web/metamask/_locales/es_419/messages.json ================================================ { "appName": { "message": "MetaMask", "description": "The name of the application" }, "appDescription": { "message": "Administración de identidad en Ethereum", "description": "The description of the application" } } ================================================ FILE: web/metamask/_locales/ja/messages.json ================================================ { "appName": { "message": "MetaMask", "description": "The name of the application" }, "appDescription": { "message": "EthereumのID管理", "description": "The description of the application" } } ================================================ FILE: web/metamask/_locales/zh_CN/messages.json ================================================ { "appName": { "message": "MetaMask", "description": "The name of the application" }, "appDescription": { "message": "以太坊身份管理", "description": "The description of the application" } } ================================================ FILE: web/metamask/background.html ================================================ MetaMask Background ================================================ FILE: web/metamask/fonts/Montserrat/OFL.txt ================================================ Copyright (c) 2011-2012, Julieta Ulanovsky (julieta.ulanovsky@gmail.com), with Reserved Font Names 'Montserrat' This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. ================================================ FILE: web/metamask/manifest.json ================================================ { "name": "MetaMask", "short_name": "Metamask", "version": "3.7.1", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", "commands": { "_execute_browser_action": { "suggested_key": { "windows": "Alt+Shift+M", "mac": "Alt+Shift+M", "chromeos": "Alt+Shift+M", "linux": "Alt+Shift+M" } } }, "icons": { "16": "images/icon-16.png", "128": "images/icon-128.png" }, "default_locale": "en", "background": { "scripts": [ "scripts/background.js" ], "persistent": true }, "browser_action": { "default_icon": { "19": "images/icon-19.png", "38": "images/icon-38.png" }, "default_title": "MetaMask", "default_popup": "popup.html" }, "content_scripts": [{ "matches": [ "file://*/*", "http://*/*", "https://*/*" ], "js": [ "scripts/contentscript.js" ], "run_at": "document_start", "all_frames": true }], "permissions": [ "storage", "clipboardWrite", "http://localhost:8545/", "https://www.cryptonator.com/" ], "web_accessible_resources": [ "scripts/inpage.js" ], "externally_connectable": { "matches": [ "https://metamask.io/*" ] } } ================================================ FILE: web/metamask/popup.html ================================================ MetaMask
================================================ FILE: web/metamask/scripts/background.js ================================================ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 && arguments[0] !== undefined ? arguments[0] : {}; var keyringController = arguments[1]; (0, _classCallCheck3.default)(this, AddressBookController); var initState = extend({ addressBook: [] }, opts.initState); this.store = new ObservableStore(initState); this.keyringController = keyringController; } // // PUBLIC METHODS // // Sets a new address book in store by accepting a new address and nickname. (0, _createClass3.default)(AddressBookController, [{ key: 'setAddressBook', value: function setAddressBook(address, name) { var _this = this; return this._addToAddressBook(address, name).then(function (addressBook) { _this.store.updateState({ addressBook: addressBook }); return _promise2.default.resolve(); }); } // // PRIVATE METHODS // // Performs the logic to add the address and name into the address book. The // pushed object is an object of two fields. Current behavior does not set an // upper limit to the number of addresses. }, { key: '_addToAddressBook', value: function _addToAddressBook(address, name) { var addressBook = this._getAddressBook(); var identities = this._getIdentities(); var addressBookIndex = addressBook.findIndex(function (element) { return element.address.toLowerCase() === address.toLowerCase() || element.name === name; }); var identitiesIndex = (0, _keys2.default)(identities).findIndex(function (element) { return element.toLowerCase() === address.toLowerCase(); } // trigger this condition if we own this address--no need to overwrite. );if (identitiesIndex !== -1) { return _promise2.default.resolve(addressBook // trigger this condition if we've seen this address before--may need to update nickname. ); } else if (addressBookIndex !== -1) { addressBook.splice(addressBookIndex, 1); } else if (addressBook.length > 15) { addressBook.shift(); } addressBook.push({ address: address, name: name }); return _promise2.default.resolve(addressBook); } // Internal method to get the address book. Current persistence behavior // should not require that this method be called from the UI directly. }, { key: '_getAddressBook', value: function _getAddressBook() { return this.store.getState().addressBook; } // Retrieves identities from the keyring controller in order to avoid // duplication }, { key: '_getIdentities', value: function _getIdentities() { return this.keyringController.memStore.getState().identities; } }]); return AddressBookController; }(); module.exports = AddressBookController; },{"babel-runtime/core-js/object/keys":85,"babel-runtime/core-js/promise":87,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"obs-store":384,"xtend":521}],6:[function(_dereq_,module,exports){ 'use strict'; var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var ObservableStore = _dereq_('obs-store'); var extend = _dereq_('xtend' // every ten minutes );var POLLING_INTERVAL = 600000; var CurrencyController = function () { function CurrencyController() { var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; (0, _classCallCheck3.default)(this, CurrencyController); var initState = extend({ currentCurrency: 'USD', conversionRate: 0, conversionDate: 'N/A' }, opts.initState); this.store = new ObservableStore(initState); } // // PUBLIC METHODS // (0, _createClass3.default)(CurrencyController, [{ key: 'getCurrentCurrency', value: function getCurrentCurrency() { return this.store.getState().currentCurrency; } }, { key: 'setCurrentCurrency', value: function setCurrentCurrency(currentCurrency) { this.store.updateState({ currentCurrency: currentCurrency }); } }, { key: 'getConversionRate', value: function getConversionRate() { return this.store.getState().conversionRate; } }, { key: 'setConversionRate', value: function setConversionRate(conversionRate) { this.store.updateState({ conversionRate: conversionRate }); } }, { key: 'getConversionDate', value: function getConversionDate() { return this.store.getState().conversionDate; } }, { key: 'setConversionDate', value: function setConversionDate(conversionDate) { this.store.updateState({ conversionDate: conversionDate }); } }, { key: 'updateConversionRate', value: function updateConversionRate() { var _this = this; var currentCurrency = this.getCurrentCurrency(); return fetch('https://www.cryptonator.com/api/ticker/eth-' + currentCurrency).then(function (response) { return response.json(); }).then(function (parsedResponse) { _this.setConversionRate(Number(parsedResponse.ticker.price)); _this.setConversionDate(Number(parsedResponse.timestamp)); }).catch(function (err) { if (err) { console.warn('MetaMask - Failed to query currency conversion.'); _this.setConversionRate(0); _this.setConversionDate('N/A'); } }); } }, { key: 'scheduleConversionInterval', value: function scheduleConversionInterval() { var _this2 = this; if (this.conversionInterval) { clearInterval(this.conversionInterval); } this.conversionInterval = setInterval(function () { _this2.updateConversionRate(); }, POLLING_INTERVAL); } }]); return CurrencyController; }(); module.exports = CurrencyController; },{"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"obs-store":384,"xtend":521}],7:[function(_dereq_,module,exports){ 'use strict'; var _keys = _dereq_('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _getPrototypeOf = _dereq_('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = _dereq_('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = _dereq_('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var EventEmitter = _dereq_('events'); var MetaMaskProvider = _dereq_('web3-provider-engine/zero.js'); var ObservableStore = _dereq_('obs-store'); var ComposedStore = _dereq_('obs-store/lib/composed'); var extend = _dereq_('xtend'); var EthQuery = _dereq_('eth-query'); var RPC_ADDRESS_LIST = _dereq_('../config.js').network; var DEFAULT_RPC = RPC_ADDRESS_LIST['rinkeby']; module.exports = function (_EventEmitter) { (0, _inherits3.default)(NetworkController, _EventEmitter); function NetworkController(config) { (0, _classCallCheck3.default)(this, NetworkController); var _this = (0, _possibleConstructorReturn3.default)(this, (NetworkController.__proto__ || (0, _getPrototypeOf2.default)(NetworkController)).call(this)); _this.networkStore = new ObservableStore('loading'); config.provider.rpcTarget = _this.getRpcAddressForType(config.provider.type, config.provider); _this.providerStore = new ObservableStore(config.provider); _this.store = new ComposedStore({ provider: _this.providerStore, network: _this.networkStore }); _this._providerListeners = {}; _this.on('networkDidChange', _this.lookupNetwork); _this.providerStore.subscribe(function (state) { return _this.switchNetwork({ rpcUrl: state.rpcTarget }); }); return _this; } (0, _createClass3.default)(NetworkController, [{ key: 'initializeProvider', value: function initializeProvider(opts) { var _this2 = this; this.providerInit = opts; this._provider = MetaMaskProvider(opts); this._proxy = new Proxy(this._provider, { get: function get(obj, name) { if (name === 'on') return _this2._on.bind(_this2); return _this2._provider[name]; }, set: function set(obj, name, value) { _this2._provider[name] = value; } }); this.provider.on('block', this._logBlock.bind(this)); this.provider.on('error', this.verifyNetwork.bind(this)); this.ethQuery = new EthQuery(this.provider); this.lookupNetwork(); return this.provider; } }, { key: 'switchNetwork', value: function switchNetwork(providerInit) { var _this3 = this; this.setNetworkState('loading'); var newInit = extend(this.providerInit, providerInit); this.providerInit = newInit; this._provider.removeAllListeners(); this._provider.stop(); this.provider = MetaMaskProvider(newInit // apply the listners created by other controllers );(0, _keys2.default)(this._providerListeners).forEach(function (key) { _this3._providerListeners[key].forEach(function (handler) { return _this3._provider.addListener(key, handler); }); }); this.emit('networkDidChange'); } }, { key: 'verifyNetwork', value: function verifyNetwork() { // Check network when restoring connectivity: if (this.isNetworkLoading()) this.lookupNetwork(); } }, { key: 'getNetworkState', value: function getNetworkState() { return this.networkStore.getState(); } }, { key: 'setNetworkState', value: function setNetworkState(network) { return this.networkStore.putState(network); } }, { key: 'isNetworkLoading', value: function isNetworkLoading() { return this.getNetworkState() === 'loading'; } }, { key: 'lookupNetwork', value: function lookupNetwork() { var _this4 = this; this.ethQuery.sendAsync({ method: 'net_version' }, function (err, network) { if (err) return _this4.setNetworkState('loading'); log.info('web3.getNetwork returned ' + network); _this4.setNetworkState(network); }); } }, { key: 'setRpcTarget', value: function setRpcTarget(rpcUrl) { this.providerStore.updateState({ type: 'rpc', rpcTarget: rpcUrl }); } }, { key: 'getCurrentRpcAddress', value: function getCurrentRpcAddress() { var provider = this.getProviderConfig(); if (!provider) return null; return this.getRpcAddressForType(provider.type); } }, { key: 'setProviderType', value: function setProviderType(type) { if (type === this.getProviderConfig().type) return; var rpcTarget = this.getRpcAddressForType(type); this.providerStore.updateState({ type: type, rpcTarget: rpcTarget }); } }, { key: 'getProviderConfig', value: function getProviderConfig() { return this.providerStore.getState(); } }, { key: 'getRpcAddressForType', value: function getRpcAddressForType(type) { var provider = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.getProviderConfig(); if (RPC_ADDRESS_LIST[type]) return RPC_ADDRESS_LIST[type]; return provider && provider.rpcTarget ? provider.rpcTarget : DEFAULT_RPC; } }, { key: '_logBlock', value: function _logBlock(block) { log.info('BLOCK CHANGED: #' + block.number.toString('hex') + ' 0x' + block.hash.toString('hex')); this.verifyNetwork(); } }, { key: '_on', value: function _on(event, handler) { if (!this._providerListeners[event]) this._providerListeners[event] = []; this._providerListeners[event].push(handler); this._provider.on(event, handler); } }, { key: 'provider', get: function get() { return this._proxy; }, set: function set(provider) { this._provider = provider; } }]); return NetworkController; }(EventEmitter); },{"../config.js":4,"babel-runtime/core-js/object/get-prototype-of":84,"babel-runtime/core-js/object/keys":85,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"babel-runtime/helpers/inherits":93,"babel-runtime/helpers/possibleConstructorReturn":94,"eth-query":298,"events":314,"obs-store":384,"obs-store/lib/composed":385,"web3-provider-engine/zero.js":517,"xtend":521}],8:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var ObservableStore = _dereq_('obs-store'); var normalizeAddress = _dereq_('eth-sig-util').normalize; var extend = _dereq_('xtend'); var PreferencesController = function () { function PreferencesController() { var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; (0, _classCallCheck3.default)(this, PreferencesController); var initState = extend({ frequentRpcList: [] }, opts.initState); this.store = new ObservableStore(initState); } // // PUBLIC METHODS // (0, _createClass3.default)(PreferencesController, [{ key: 'setSelectedAddress', value: function setSelectedAddress(_address) { var _this = this; return new _promise2.default(function (resolve, reject) { var address = normalizeAddress(_address); _this.store.updateState({ selectedAddress: address }); resolve(); }); } }, { key: 'getSelectedAddress', value: function getSelectedAddress(_address) { return this.store.getState().selectedAddress; } }, { key: 'updateFrequentRpcList', value: function updateFrequentRpcList(_url) { var _this2 = this; return this.addToFrequentRpcList(_url).then(function (rpcList) { _this2.store.updateState({ frequentRpcList: rpcList }); return _promise2.default.resolve(); }); } }, { key: 'addToFrequentRpcList', value: function addToFrequentRpcList(_url) { var rpcList = this.getFrequentRpcList(); var index = rpcList.findIndex(function (element) { return element === _url; }); if (index !== -1) { rpcList.splice(index, 1); } if (_url !== 'http://localhost:8545') { rpcList.push(_url); } if (rpcList.length > 2) { rpcList.shift(); } return _promise2.default.resolve(rpcList); } }, { key: 'getFrequentRpcList', value: function getFrequentRpcList() { return this.store.getState().frequentRpcList; } // // PRIVATE METHODS // }]); return PreferencesController; }(); module.exports = PreferencesController; },{"babel-runtime/core-js/promise":87,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"eth-sig-util":299,"obs-store":384,"xtend":521}],9:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var ObservableStore = _dereq_('obs-store'); var extend = _dereq_('xtend' // every three seconds when an incomplete tx is waiting );var POLLING_INTERVAL = 3000; var ShapeshiftController = function () { function ShapeshiftController() { var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; (0, _classCallCheck3.default)(this, ShapeshiftController); var initState = extend({ shapeShiftTxList: [] }, opts.initState); this.store = new ObservableStore(initState); this.pollForUpdates(); } // // PUBLIC METHODS // (0, _createClass3.default)(ShapeshiftController, [{ key: 'getShapeShiftTxList', value: function getShapeShiftTxList() { var shapeShiftTxList = this.store.getState().shapeShiftTxList; return shapeShiftTxList; } }, { key: 'getPendingTxs', value: function getPendingTxs() { var txs = this.getShapeShiftTxList(); var pending = txs.filter(function (tx) { return tx.response && tx.response.status !== 'complete'; }); return pending; } }, { key: 'pollForUpdates', value: function pollForUpdates() { var _this = this; var pendingTxs = this.getPendingTxs(); if (pendingTxs.length === 0) { return; } _promise2.default.all(pendingTxs.map(function (tx) { return _this.updateTx(tx); })).then(function (results) { results.forEach(function (tx) { return _this.saveTx(tx); }); _this.timeout = setTimeout(_this.pollForUpdates.bind(_this), POLLING_INTERVAL); }); } }, { key: 'updateTx', value: function updateTx(tx) { var url = 'https://shapeshift.io/txStat/' + tx.depositAddress; return fetch(url).then(function (response) { return response.json(); }).then(function (json) { tx.response = json; if (tx.response.status === 'complete') { tx.time = new Date().getTime(); } return tx; }); } }, { key: 'saveTx', value: function saveTx(tx) { var _store$getState = this.store.getState(), shapeShiftTxList = _store$getState.shapeShiftTxList; var index = shapeShiftTxList.indexOf(tx); if (index !== -1) { shapeShiftTxList[index] = tx; this.store.updateState({ shapeShiftTxList: shapeShiftTxList }); } } }, { key: 'removeShapeShiftTx', value: function removeShapeShiftTx(tx) { var _store$getState2 = this.store.getState(), shapeShiftTxList = _store$getState2.shapeShiftTxList; var index = shapeShiftTxList.indexOf(index); if (index !== -1) { shapeShiftTxList.splice(index, 1); } this.updateState({ shapeShiftTxList: shapeShiftTxList }); } }, { key: 'createShapeShiftTx', value: function createShapeShiftTx(depositAddress, depositType) { var state = this.store.getState(); var shapeShiftTxList = state.shapeShiftTxList; var shapeShiftTx = { depositAddress: depositAddress, depositType: depositType, key: 'shapeshift', time: new Date().getTime(), response: {} }; if (!shapeShiftTxList) { shapeShiftTxList = [shapeShiftTx]; } else { shapeShiftTxList.push(shapeShiftTx); } this.store.updateState({ shapeShiftTxList: shapeShiftTxList }); this.pollForUpdates(); } }]); return ShapeshiftController; }(); module.exports = ShapeshiftController; },{"babel-runtime/core-js/promise":87,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"obs-store":384,"xtend":521}],10:[function(_dereq_,module,exports){ (function (global){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _keys = _dereq_('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _isNan = _dereq_('babel-runtime/core-js/number/is-nan'); var _isNan2 = _interopRequireDefault(_isNan); var _getPrototypeOf = _dereq_('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = _dereq_('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = _dereq_('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var EventEmitter = _dereq_('events'); var async = _dereq_('async'); var extend = _dereq_('xtend'); var Semaphore = _dereq_('semaphore'); var ObservableStore = _dereq_('obs-store'); var ethUtil = _dereq_('ethereumjs-util'); var TxProviderUtil = _dereq_('../lib/tx-utils'); var createId = _dereq_('../lib/random-id'); var denodeify = _dereq_('denodeify'); var RETRY_LIMIT = 200; var RESUBMIT_INTERVAL = 10000; // Ten seconds module.exports = function (_EventEmitter) { (0, _inherits3.default)(TransactionController, _EventEmitter); function TransactionController(opts) { (0, _classCallCheck3.default)(this, TransactionController); var _this = (0, _possibleConstructorReturn3.default)(this, (TransactionController.__proto__ || (0, _getPrototypeOf2.default)(TransactionController)).call(this)); _this.store = new ObservableStore(extend({ transactions: [] }, opts.initState)); _this.memStore = new ObservableStore({}); _this.networkStore = opts.networkStore || new ObservableStore({}); _this.preferencesStore = opts.preferencesStore || new ObservableStore({}); _this.txHistoryLimit = opts.txHistoryLimit; _this.provider = opts.provider; _this.blockTracker = opts.blockTracker; _this.query = opts.ethQuery; _this.txProviderUtils = new TxProviderUtil(_this.query); _this.blockTracker.on('block', _this.checkForTxInBlock.bind(_this)); _this.signEthTx = opts.signTransaction; _this.nonceLock = Semaphore(1 // memstore is computed from a few different stores );_this._updateMemstore(); _this.store.subscribe(function () { return _this._updateMemstore(); }); _this.networkStore.subscribe(function () { return _this._updateMemstore(); }); _this.preferencesStore.subscribe(function () { return _this._updateMemstore(); }); _this.continuallyResubmitPendingTxs(); return _this; } (0, _createClass3.default)(TransactionController, [{ key: 'getState', value: function getState() { return this.memStore.getState(); } }, { key: 'getNetwork', value: function getNetwork() { return this.networkStore.getState(); } }, { key: 'getSelectedAddress', value: function getSelectedAddress() { return this.preferencesStore.getState().selectedAddress; } // Returns the tx list }, { key: 'getTxList', value: function getTxList() { var network = this.getNetwork(); var fullTxList = this.getFullTxList(); return fullTxList.filter(function (txMeta) { return txMeta.metamaskNetworkId === network; }); } // Returns the number of txs for the current network. }, { key: 'getTxCount', value: function getTxCount() { return this.getTxList().length; } // Returns the full tx list across all networks }, { key: 'getFullTxList', value: function getFullTxList() { return this.store.getState().transactions; } // Adds a tx to the txlist }, { key: 'addTx', value: function addTx(txMeta) { var txCount = this.getTxCount(); var network = this.getNetwork(); var fullTxList = this.getFullTxList(); var txHistoryLimit = this.txHistoryLimit; // checks if the length of the tx history is // longer then desired persistence limit // and then if it is removes only confirmed // or rejected tx's. // not tx's that are pending or unapproved if (txCount > txHistoryLimit - 1) { var index = fullTxList.findIndex(function (metaTx) { return (metaTx.status === 'confirmed' || metaTx.status === 'rejected') && network === txMeta.metamaskNetworkId; }); fullTxList.splice(index, 1); } fullTxList.push(txMeta); this._saveTxList(fullTxList); this.emit('update'); this.once(txMeta.id + ':signed', function (txId) { this.removeAllListeners(txMeta.id + ':rejected'); }); this.once(txMeta.id + ':rejected', function (txId) { this.removeAllListeners(txMeta.id + ':signed'); }); this.emit('updateBadge'); this.emit(txMeta.id + ':unapproved', txMeta); } // gets tx by Id and returns it }, { key: 'getTx', value: function getTx(txId, cb) { var txList = this.getTxList(); var txMeta = txList.find(function (txData) { return txData.id === txId; }); return cb ? cb(txMeta) : txMeta; } // }, { key: 'updateTx', value: function updateTx(txMeta) { var txId = txMeta.id; var txList = this.getFullTxList(); var index = txList.findIndex(function (txData) { return txData.id === txId; }); txList[index] = txMeta; this._saveTxList(txList); this.emit('update'); } }, { key: 'addUnapprovedTransaction', value: function addUnapprovedTransaction(txParams, done) { var _this2 = this; var txMeta = void 0; async.waterfall([ // validate function (cb) { return _this2.txProviderUtils.validateTxParams(txParams, cb); }, // construct txMeta function (cb) { txMeta = { id: createId(), time: new Date().getTime(), status: 'unapproved', metamaskNetworkId: _this2.getNetwork(), txParams: txParams }; cb(); }, // add default tx params function (cb) { return _this2.addTxDefaults(txMeta, cb); }, // save txMeta function (cb) { _this2.addTx(txMeta); cb(null, txMeta); }], done); } }, { key: 'addTxDefaults', value: function addTxDefaults(txMeta, cb) { var _this3 = this; var txParams = txMeta.txParams; // ensure value txParams.value = txParams.value || '0x0'; this.query.gasPrice(function (err, gasPrice) { if (err) return cb(err // set gasPrice );txParams.gasPrice = gasPrice; // set gasLimit _this3.txProviderUtils.analyzeGasUsage(txMeta, cb); }); } }, { key: 'getUnapprovedTxList', value: function getUnapprovedTxList() { var txList = this.getTxList(); return txList.filter(function (txMeta) { return txMeta.status === 'unapproved'; }).reduce(function (result, tx) { result[tx.id] = tx; return result; }, {}); } }, { key: 'approveTransaction', value: function approveTransaction(txId) { var _this4 = this; var cb = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : warn; var self = this; // approve self.setTxStatusApproved(txId // only allow one tx at a time for atomic nonce usage );self.nonceLock.take(function () { // begin signature process async.waterfall([function (cb) { return self.fillInTxParams(txId, cb); }, function (cb) { return self.signTransaction(txId, cb); }, function (rawTx, cb) { return self.publishTransaction(txId, rawTx, cb); }], function (err) { self.nonceLock.leave(); if (err) { _this4.setTxStatusFailed(txId, { errCode: err.errCode || err, message: err.message || 'Transaction failed during approval' }); return cb(err); } cb(); }); }); } }, { key: 'cancelTransaction', value: function cancelTransaction(txId) { var cb = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : warn; this.setTxStatusRejected(txId); cb(); } }, { key: 'fillInTxParams', value: function fillInTxParams(txId, cb) { var _this5 = this; var txMeta = this.getTx(txId); this.txProviderUtils.fillInTxParams(txMeta.txParams, function (err) { if (err) return cb(err); _this5.updateTx(txMeta); cb(); }); } }, { key: 'getChainId', value: function getChainId() { var networkState = this.networkStore.getState(); var getChainId = parseInt(networkState.network); if ((0, _isNan2.default)(getChainId)) { return 0; } else { return getChainId; } } }, { key: 'signTransaction', value: function signTransaction(txId, cb) { var _this6 = this; var txMeta = this.getTx(txId); var txParams = txMeta.txParams; var fromAddress = txParams.from; // add network/chain id txParams.chainId = this.getChainId(); var ethTx = this.txProviderUtils.buildEthTxFromParams(txParams); this.signEthTx(ethTx, fromAddress).then(function () { _this6.setTxStatusSigned(txMeta.id); cb(null, ethUtil.bufferToHex(ethTx.serialize())); }).catch(function (err) { cb(err); }); } }, { key: 'publishTransaction', value: function publishTransaction(txId, rawTx) { var _this7 = this; var cb = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : warn; var txMeta = this.getTx(txId); txMeta.rawTx = rawTx; this.updateTx(txMeta); this.txProviderUtils.publishTransaction(rawTx, function (err, txHash) { if (err) return cb(err); _this7.setTxHash(txId, txHash); _this7.setTxStatusSubmitted(txId); cb(); }); } // receives a txHash records the tx as signed }, { key: 'setTxHash', value: function setTxHash(txId, txHash) { // Add the tx hash to the persisted meta-tx object var txMeta = this.getTx(txId); txMeta.hash = txHash; this.updateTx(txMeta); } /* Takes an object of fields to search for eg: var thingsToLookFor = { to: '0x0..', from: '0x0..', status: 'signed', } and returns a list of tx with all options matching this is for things like filtering a the tx list for only tx's from 1 account or for filltering for all txs from one account and that have been 'confirmed' */ }, { key: 'getFilteredTxList', value: function getFilteredTxList(opts) { var _this8 = this; var filteredTxList; (0, _keys2.default)(opts).forEach(function (key) { filteredTxList = _this8.getTxsByMetaData(key, opts[key], filteredTxList); }); return filteredTxList; } }, { key: 'getTxsByMetaData', value: function getTxsByMetaData(key, value) { var txList = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.getTxList(); return txList.filter(function (txMeta) { if (txMeta.txParams[key]) { return txMeta.txParams[key] === value; } else { return txMeta[key] === value; } }); } // STATUS METHODS // get::set status // should return the status of the tx. }, { key: 'getTxStatus', value: function getTxStatus(txId) { var txMeta = this.getTx(txId); return txMeta.status; } // should update the status of the tx to 'rejected'. }, { key: 'setTxStatusRejected', value: function setTxStatusRejected(txId) { this._setTxStatus(txId, 'rejected'); } // should update the status of the tx to 'approved'. }, { key: 'setTxStatusApproved', value: function setTxStatusApproved(txId) { this._setTxStatus(txId, 'approved'); } // should update the status of the tx to 'signed'. }, { key: 'setTxStatusSigned', value: function setTxStatusSigned(txId) { this._setTxStatus(txId, 'signed'); } // should update the status of the tx to 'submitted'. }, { key: 'setTxStatusSubmitted', value: function setTxStatusSubmitted(txId) { this._setTxStatus(txId, 'submitted'); } // should update the status of the tx to 'confirmed'. }, { key: 'setTxStatusConfirmed', value: function setTxStatusConfirmed(txId) { this._setTxStatus(txId, 'confirmed'); } }, { key: 'setTxStatusFailed', value: function setTxStatusFailed(txId, reason) { var txMeta = this.getTx(txId); txMeta.err = reason; this.updateTx(txMeta); this._setTxStatus(txId, 'failed'); } // merges txParams obj onto txData.txParams // use extend to ensure that all fields are filled }, { key: 'updateTxParams', value: function updateTxParams(txId, txParams) { var txMeta = this.getTx(txId); txMeta.txParams = extend(txMeta.txParams, txParams); this.updateTx(txMeta); } // checks if a signed tx is in a block and // if included sets the tx status as 'confirmed' }, { key: 'checkForTxInBlock', value: function checkForTxInBlock() { var _this9 = this; var signedTxList = this.getFilteredTxList({ status: 'submitted' }); if (!signedTxList.length) return; signedTxList.forEach(function (txMeta) { var txHash = txMeta.hash; var txId = txMeta.id; if (!txHash) { var errReason = { errCode: 'No hash was provided', message: 'We had an error while submitting this transaction, please try again.' }; return _this9.setTxStatusFailed(txId, errReason); } _this9.query.getTransactionByHash(txHash, function (err, txParams) { if (err || !txParams) { if (!txParams) return; txMeta.err = { isWarning: true, errorCode: err, message: 'There was a problem loading this transaction.' }; _this9.updateTx(txMeta); return log.error(err); } if (txParams.blockNumber) { _this9.setTxStatusConfirmed(txId); } }); }); } // PRIVATE METHODS // Should find the tx in the tx list and // update it. // should set the status in txData // - `'unapproved'` the user has not responded // - `'rejected'` the user has responded no! // - `'approved'` the user has approved the tx // - `'signed'` the tx is signed // - `'submitted'` the tx is sent to a server // - `'confirmed'` the tx has been included in a block. }, { key: '_setTxStatus', value: function _setTxStatus(txId, status) { var txMeta = this.getTx(txId); txMeta.status = status; this.emit(txMeta.id + ':' + status, txId); if (status === 'submitted' || status === 'rejected') { this.emit(txMeta.id + ':finished', txMeta); } this.updateTx(txMeta); this.emit('updateBadge'); } // Saves the new/updated txList. // Function is intended only for internal use }, { key: '_saveTxList', value: function _saveTxList(transactions) { this.store.updateState({ transactions: transactions }); } }, { key: '_updateMemstore', value: function _updateMemstore() { var unapprovedTxs = this.getUnapprovedTxList(); var selectedAddressTxList = this.getFilteredTxList({ from: this.getSelectedAddress(), metamaskNetworkId: this.getNetwork() }); this.memStore.updateState({ unapprovedTxs: unapprovedTxs, selectedAddressTxList: selectedAddressTxList }); } }, { key: 'continuallyResubmitPendingTxs', value: function continuallyResubmitPendingTxs() { var _this10 = this; var pending = this.getTxsByMetaData('status', 'submitted'); var resubmit = denodeify(this.resubmitTx.bind(this)); _promise2.default.all(pending.map(function (txMeta) { return resubmit(txMeta); })).catch(function (reason) { log.info('Problem resubmitting tx', reason); }).then(function () { global.setTimeout(function () { _this10.continuallyResubmitPendingTxs(); }, RESUBMIT_INTERVAL); }); } }, { key: 'resubmitTx', value: function resubmitTx(txMeta, cb) { // Increment a try counter. if (!('retryCount' in txMeta)) { txMeta.retryCount = 0; } // Only auto-submit already-signed txs: if (!('rawTx' in txMeta)) { return cb(); } if (txMeta.retryCount > RETRY_LIMIT) { txMeta.err = { isWarning: true, message: 'Gave up submitting tx.' }; this.updateTx(txMeta); return log.error(txMeta.err.message); } txMeta.retryCount++; var rawTx = txMeta.rawTx; this.txProviderUtils.publishTransaction(rawTx, cb); } }, { key: 'unapprovedTxCount', get: function get() { return (0, _keys2.default)(this.getUnapprovedTxList()).length; } }, { key: 'pendingTxCount', get: function get() { return this.getTxsByMetaData('status', 'signed').length; } }]); return TransactionController; }(EventEmitter); var warn = function warn() { return log.warn('warn was used no cb provided'); }; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"../lib/random-id":24,"../lib/tx-utils":26,"async":77,"babel-runtime/core-js/number/is-nan":79,"babel-runtime/core-js/object/get-prototype-of":84,"babel-runtime/core-js/object/keys":85,"babel-runtime/core-js/promise":87,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"babel-runtime/helpers/inherits":93,"babel-runtime/helpers/possibleConstructorReturn":94,"denodeify":257,"ethereumjs-util":309,"events":314,"obs-store":384,"semaphore":445,"xtend":521}],11:[function(_dereq_,module,exports){ 'use strict'; // // The default state of MetaMask // module.exports = { config: {}, NetworkController: { provider: { type: 'rinkeby' } } }; },{}],12:[function(_dereq_,module,exports){ 'use strict'; var _keys = _dereq_('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _getPrototypeOf = _dereq_('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = _dereq_('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = _dereq_('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var ethUtil = _dereq_('ethereumjs-util'); var BN = ethUtil.BN; var bip39 = _dereq_('bip39'); var EventEmitter = _dereq_('events').EventEmitter; var ObservableStore = _dereq_('obs-store'); var filter = _dereq_('promise-filter'); var encryptor = _dereq_('browser-passworder'); var sigUtil = _dereq_('eth-sig-util'); var normalizeAddress = sigUtil.normalize; // Keyrings: var SimpleKeyring = _dereq_('eth-simple-keyring'); var HdKeyring = _dereq_('eth-hd-keyring'); var keyringTypes = [SimpleKeyring, HdKeyring]; var KeyringController = function (_EventEmitter) { (0, _inherits3.default)(KeyringController, _EventEmitter); // PUBLIC METHODS // // THE FIRST SECTION OF METHODS ARE PUBLIC-FACING, // MEANING THEY ARE USED BY CONSUMERS OF THIS CLASS. // // THEIR SURFACE AREA SHOULD BE CHANGED WITH GREAT CARE. function KeyringController(opts) { (0, _classCallCheck3.default)(this, KeyringController); var _this = (0, _possibleConstructorReturn3.default)(this, (KeyringController.__proto__ || (0, _getPrototypeOf2.default)(KeyringController)).call(this)); var initState = opts.initState || {}; _this.keyringTypes = keyringTypes; _this.store = new ObservableStore(initState); _this.memStore = new ObservableStore({ isUnlocked: false, keyringTypes: _this.keyringTypes.map(function (krt) { return krt.type; }), keyrings: [], identities: {} }); _this.ethStore = opts.ethStore; _this.encryptor = encryptor; _this.keyrings = []; _this.getNetwork = opts.getNetwork; return _this; } // Full Update // returns Promise( @object state ) // // Emits the `update` event and // returns a Promise that resolves to the current state. // // Frequently used to end asynchronous chains in this class, // indicating consumers can often either listen for updates, // or accept a state-resolving promise to consume their results. // // Not all methods end with this, that might be a nice refactor. (0, _createClass3.default)(KeyringController, [{ key: 'fullUpdate', value: function fullUpdate() { this.emit('update'); return _promise2.default.resolve(this.memStore.getState()); } // Create New Vault And Keychain // @string password - The password to encrypt the vault with // // returns Promise( @object state ) // // Destroys any old encrypted storage, // creates a new encrypted store with the given password, // randomly creates a new HD wallet with 1 account, // faucets that account on the testnet. }, { key: 'createNewVaultAndKeychain', value: function createNewVaultAndKeychain(password) { return this.persistAllKeyrings(password).then(this.createFirstKeyTree.bind(this)).then(this.fullUpdate.bind(this)); } // CreateNewVaultAndRestore // @string password - The password to encrypt the vault with // @string seed - The BIP44-compliant seed phrase. // // returns Promise( @object state ) // // Destroys any old encrypted storage, // creates a new encrypted store with the given password, // creates a new HD wallet from the given seed with 1 account. }, { key: 'createNewVaultAndRestore', value: function createNewVaultAndRestore(password, seed) { var _this2 = this; if (typeof password !== 'string') { return _promise2.default.reject('Password must be text.'); } if (!bip39.validateMnemonic(seed)) { return _promise2.default.reject('Seed phrase is invalid.'); } this.clearKeyrings(); return this.persistAllKeyrings(password).then(function () { return _this2.addNewKeyring('HD Key Tree', { mnemonic: seed, numberOfAccounts: 1 }); }).then(function (firstKeyring) { return firstKeyring.getAccounts(); }).then(function (accounts) { var firstAccount = accounts[0]; if (!firstAccount) throw new Error('KeyringController - First Account not found.'); var hexAccount = normalizeAddress(firstAccount); _this2.emit('newAccount', hexAccount); return _this2.setupAccounts(accounts); }).then(this.persistAllKeyrings.bind(this, password)).then(this.fullUpdate.bind(this)); } // Set Locked // returns Promise( @object state ) // // This method deallocates all secrets, and effectively locks metamask. }, { key: 'setLocked', value: function setLocked() { // set locked this.password = null; this.memStore.updateState({ isUnlocked: false } // remove keyrings );this.keyrings = []; this._updateMemStoreKeyrings(); return this.fullUpdate(); } // Submit Password // @string password // // returns Promise( @object state ) // // Attempts to decrypt the current vault and load its keyrings // into memory. // // Temporarily also migrates any old-style vaults first, as well. // (Pre MetaMask 3.0.0) }, { key: 'submitPassword', value: function submitPassword(password) { var _this3 = this; return this.unlockKeyrings(password).then(function (keyrings) { _this3.keyrings = keyrings; return _this3.fullUpdate(); }); } // Add New Keyring // @string type // @object opts // // returns Promise( @Keyring keyring ) // // Adds a new Keyring of the given `type` to the vault // and the current decrypted Keyrings array. // // All Keyring classes implement a unique `type` string, // and this is used to retrieve them from the keyringTypes array. }, { key: 'addNewKeyring', value: function addNewKeyring(type, opts) { var _this4 = this; var Keyring = this.getKeyringClassForType(type); var keyring = new Keyring(opts); return keyring.deserialize(opts).then(function () { return keyring.getAccounts(); }).then(function (accounts) { return _this4.checkForDuplicate(type, accounts); }).then(function (checkedAccounts) { _this4.keyrings.push(keyring); return _this4.setupAccounts(checkedAccounts); }).then(function () { return _this4.persistAllKeyrings(); }).then(function () { return _this4.fullUpdate(); }).then(function () { _this4._updateMemStoreKeyrings(); return keyring; }); } // For now just checks for simple key pairs // but in the future // should possibly add HD and other types // }, { key: 'checkForDuplicate', value: function checkForDuplicate(type, newAccount) { return this.getAccounts().then(function (accounts) { switch (type) { case 'Simple Key Pair': var isNotIncluded = !accounts.find(function (key) { return key === newAccount[0] || key === ethUtil.stripHexPrefix(newAccount[0]); }); return isNotIncluded ? _promise2.default.resolve(newAccount) : _promise2.default.reject(new Error('The account you\'re are trying to import is a duplicate')); default: return _promise2.default.resolve(newAccount); } }); } // Add New Account // @number keyRingNum // // returns Promise( @object state ) // // Calls the `addAccounts` method on the Keyring // in the kryings array at index `keyringNum`, // and then saves those changes. }, { key: 'addNewAccount', value: function addNewAccount(selectedKeyring) { return selectedKeyring.addAccounts(1).then(this.setupAccounts.bind(this)).then(this.persistAllKeyrings.bind(this)).then(this.fullUpdate.bind(this)); } // Save Account Label // @string account // @string label // // returns Promise( @string label ) // // Persists a nickname equal to `label` for the specified account. }, { key: 'saveAccountLabel', value: function saveAccountLabel(account, label) { try { var hexAddress = normalizeAddress(account // update state on diskStore );var state = this.store.getState(); var walletNicknames = state.walletNicknames || {}; walletNicknames[hexAddress] = label; this.store.updateState({ walletNicknames: walletNicknames } // update state on memStore );var identities = this.memStore.getState().identities; identities[hexAddress].name = label; this.memStore.updateState({ identities: identities }); return _promise2.default.resolve(label); } catch (err) { return _promise2.default.reject(err); } } // Export Account // @string address // // returns Promise( @string privateKey ) // // Requests the private key from the keyring controlling // the specified address. // // Returns a Promise that may resolve with the private key string. }, { key: 'exportAccount', value: function exportAccount(address) { try { return this.getKeyringForAccount(address).then(function (keyring) { return keyring.exportAccount(normalizeAddress(address)); }); } catch (e) { return _promise2.default.reject(e); } } // SIGNING METHODS // // This method signs tx and returns a promise for // TX Manager to update the state after signing }, { key: 'signTransaction', value: function signTransaction(ethTx, _fromAddress) { var fromAddress = normalizeAddress(_fromAddress); return this.getKeyringForAccount(fromAddress).then(function (keyring) { return keyring.signTransaction(fromAddress, ethTx); }); } // Sign Message // @object msgParams // // returns Promise(@buffer rawSig) // // Attempts to sign the provided @object msgParams. }, { key: 'signMessage', value: function signMessage(msgParams) { var address = normalizeAddress(msgParams.from); return this.getKeyringForAccount(address).then(function (keyring) { return keyring.signMessage(address, msgParams.data); }); } // Sign Personal Message // @object msgParams // // returns Promise(@buffer rawSig) // // Attempts to sign the provided @object msgParams. // Prefixes the hash before signing as per the new geth behavior. }, { key: 'signPersonalMessage', value: function signPersonalMessage(msgParams) { var address = normalizeAddress(msgParams.from); return this.getKeyringForAccount(address).then(function (keyring) { return keyring.signPersonalMessage(address, msgParams.data); }); } // PRIVATE METHODS // // THESE METHODS ARE ONLY USED INTERNALLY TO THE KEYRING-CONTROLLER // AND SO MAY BE CHANGED MORE LIBERALLY THAN THE ABOVE METHODS. // Create First Key Tree // returns @Promise // // Clears the vault, // creates a new one, // creates a random new HD Keyring with 1 account, // makes that account the selected account, // faucets that account on testnet, // puts the current seed words into the state tree. }, { key: 'createFirstKeyTree', value: function createFirstKeyTree() { var _this5 = this; this.clearKeyrings(); return this.addNewKeyring('HD Key Tree', { numberOfAccounts: 1 }).then(function (keyring) { return keyring.getAccounts(); }).then(function (accounts) { var firstAccount = accounts[0]; if (!firstAccount) throw new Error('KeyringController - No account found on keychain.'); var hexAccount = normalizeAddress(firstAccount); _this5.emit('newAccount', hexAccount); _this5.emit('newVault', hexAccount); return _this5.setupAccounts(accounts); }).then(this.persistAllKeyrings.bind(this)); } // Setup Accounts // @array accounts // // returns @Promise(@object account) // // Initializes the provided account array // Gives them numerically incremented nicknames, // and adds them to the ethStore for regular balance checking. }, { key: 'setupAccounts', value: function setupAccounts(accounts) { var _this6 = this; return this.getAccounts().then(function (loadedAccounts) { var arr = accounts || loadedAccounts; return _promise2.default.all(arr.map(function (account) { return _this6.getBalanceAndNickname(account); })); }); } // Get Balance And Nickname // @string account // // returns Promise( @string label ) // // Takes an account address and an iterator representing // the current number of named accounts. }, { key: 'getBalanceAndNickname', value: function getBalanceAndNickname(account) { if (!account) { throw new Error('Problem loading account.'); } var address = normalizeAddress(account); this.ethStore.addAccount(address); return this.createNickname(address); } // Create Nickname // @string address // // returns Promise( @string label ) // // Takes an address, and assigns it an incremented nickname, persisting it. }, { key: 'createNickname', value: function createNickname(address) { var hexAddress = normalizeAddress(address); var identities = this.memStore.getState().identities; var currentIdentityCount = (0, _keys2.default)(identities).length + 1; var nicknames = this.store.getState().walletNicknames || {}; var existingNickname = nicknames[hexAddress]; var name = existingNickname || 'Account ' + currentIdentityCount; identities[hexAddress] = { address: hexAddress, name: name }; this.memStore.updateState({ identities: identities }); return this.saveAccountLabel(hexAddress, name); } // Persist All Keyrings // @password string // // returns Promise // // Iterates the current `keyrings` array, // serializes each one into a serialized array, // encrypts that array with the provided `password`, // and persists that encrypted string to storage. }, { key: 'persistAllKeyrings', value: function persistAllKeyrings() { var _this7 = this; var password = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.password; if (typeof password === 'string') { this.password = password; this.memStore.updateState({ isUnlocked: true }); } return _promise2.default.all(this.keyrings.map(function (keyring) { return _promise2.default.all([keyring.type, keyring.serialize()]).then(function (serializedKeyringArray) { // Label the output values on each serialized Keyring: return { type: serializedKeyringArray[0], data: serializedKeyringArray[1] }; }); })).then(function (serializedKeyrings) { return _this7.encryptor.encrypt(_this7.password, serializedKeyrings); }).then(function (encryptedString) { _this7.store.updateState({ vault: encryptedString }); return true; }); } // Unlock Keyrings // @string password // // returns Promise( @array keyrings ) // // Attempts to unlock the persisted encrypted storage, // initializing the persisted keyrings to RAM. }, { key: 'unlockKeyrings', value: function unlockKeyrings(password) { var _this8 = this; var encryptedVault = this.store.getState().vault; if (!encryptedVault) { throw new Error('Cannot unlock without a previous vault.'); } return this.encryptor.decrypt(password, encryptedVault).then(function (vault) { _this8.password = password; _this8.memStore.updateState({ isUnlocked: true }); vault.forEach(_this8.restoreKeyring.bind(_this8)); return _this8.keyrings; }); } // Restore Keyring // @object serialized // // returns Promise( @Keyring deserialized ) // // Attempts to initialize a new keyring from the provided // serialized payload. // // On success, returns the resulting @Keyring instance. }, { key: 'restoreKeyring', value: function restoreKeyring(serialized) { var _this9 = this; var type = serialized.type, data = serialized.data; var Keyring = this.getKeyringClassForType(type); var keyring = new Keyring(); return keyring.deserialize(data).then(function () { return keyring.getAccounts(); }).then(function (accounts) { return _this9.setupAccounts(accounts); }).then(function () { _this9.keyrings.push(keyring); _this9._updateMemStoreKeyrings(); return keyring; }); } // Get Keyring Class For Type // @string type // // Returns @class Keyring // // Searches the current `keyringTypes` array // for a Keyring class whose unique `type` property // matches the provided `type`, // returning it if it exists. }, { key: 'getKeyringClassForType', value: function getKeyringClassForType(type) { return this.keyringTypes.find(function (kr) { return kr.type === type; }); } }, { key: 'getKeyringsByType', value: function getKeyringsByType(type) { return this.keyrings.filter(function (keyring) { return keyring.type === type; }); } // Get Accounts // returns Promise( @Array[ @string accounts ] ) // // Returns the public addresses of all current accounts // managed by all currently unlocked keyrings. }, { key: 'getAccounts', value: function getAccounts() { var keyrings = this.keyrings || []; return _promise2.default.all(keyrings.map(function (kr) { return kr.getAccounts(); })).then(function (keyringArrays) { return keyringArrays.reduce(function (res, arr) { return res.concat(arr); }, []); }); } // Get Keyring For Account // @string address // // returns Promise(@Keyring keyring) // // Returns the currently initialized keyring that manages // the specified `address` if one exists. }, { key: 'getKeyringForAccount', value: function getKeyringForAccount(address) { var hexed = normalizeAddress(address); log.debug('KeyringController - getKeyringForAccount: ' + hexed); return _promise2.default.all(this.keyrings.map(function (keyring) { return _promise2.default.all([keyring, keyring.getAccounts()]); })).then(filter(function (candidate) { var accounts = candidate[1].map(normalizeAddress); return accounts.includes(hexed); })).then(function (winners) { if (winners && winners.length > 0) { return winners[0][0]; } else { throw new Error('No keyring found for the requested account.'); } }); } // Display For Keyring // @Keyring keyring // // returns Promise( @Object { type:String, accounts:Array } ) // // Is used for adding the current keyrings to the state object. }, { key: 'displayForKeyring', value: function displayForKeyring(keyring) { return keyring.getAccounts().then(function (accounts) { return { type: keyring.type, accounts: accounts }; }); } // Add Gas Buffer // @string gas (as hexadecimal value) // // returns @string bufferedGas (as hexadecimal value) // // Adds a healthy buffer of gas to an initial gas estimate. }, { key: 'addGasBuffer', value: function addGasBuffer(gas) { var gasBuffer = new BN('100000', 10); var bnGas = new BN(ethUtil.stripHexPrefix(gas), 16); var correct = bnGas.add(gasBuffer); return ethUtil.addHexPrefix(correct.toString(16)); } // Clear Keyrings // // Deallocates all currently managed keyrings and accounts. // Used before initializing a new vault. }, { key: 'clearKeyrings', value: function clearKeyrings() { var _this10 = this; var accounts = void 0; try { accounts = (0, _keys2.default)(this.ethStore.getState()); } catch (e) { accounts = []; } accounts.forEach(function (address) { _this10.ethStore.removeAccount(address); } // clear keyrings from memory );this.keyrings = []; this.memStore.updateState({ keyrings: [], identities: {} }); } }, { key: '_updateMemStoreKeyrings', value: function _updateMemStoreKeyrings() { var _this11 = this; _promise2.default.all(this.keyrings.map(this.displayForKeyring)).then(function (keyrings) { _this11.memStore.updateState({ keyrings: keyrings }); }); } }]); return KeyringController; }(EventEmitter); module.exports = KeyringController; },{"babel-runtime/core-js/object/get-prototype-of":84,"babel-runtime/core-js/object/keys":85,"babel-runtime/core-js/promise":87,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"babel-runtime/helpers/inherits":93,"babel-runtime/helpers/possibleConstructorReturn":94,"bip39":99,"browser-passworder":108,"eth-hd-keyring":295,"eth-sig-util":299,"eth-simple-keyring":302,"ethereumjs-util":309,"events":314,"obs-store":384,"promise-filter":403}],13:[function(_dereq_,module,exports){ (function (process,global){ 'use strict'; var uri = 'https://faucet.metamask.io/'; var METAMASK_DEBUG = undefined; var env = process.env.METAMASK_ENV; module.exports = function (address) { // Don't faucet in development or test if (METAMASK_DEBUG === true || env === 'test') return; global.log.info('auto-fauceting:', address); var data = address; var headers = new Headers(); headers.append('Content-type', 'application/rawdata'); fetch(uri, { method: 'POST', headers: headers, body: data }).catch(function (err) { console.error(err); }); }; }).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"_process":402}],14:[function(_dereq_,module,exports){ 'use strict'; module.exports = getBuyEthUrl; function getBuyEthUrl(_ref) { var network = _ref.network, amount = _ref.amount, address = _ref.address; var url = void 0; switch (network) { case '1': url = 'https://buy.coinbase.com/?code=9ec56d01-7e81-5017-930c-513daa27bb6a&amount=' + amount + '&address=' + address + '&crypto_currency=ETH'; break; case '3': url = 'https://faucet.metamask.io/'; break; case '4': url = 'https://www.rinkeby.io/'; break; case '42': url = 'https://github.com/kovan-testnet/faucet'; break; } return url; } },{}],15:[function(_dereq_,module,exports){ 'use strict'; var ethUtil = _dereq_('ethereumjs-util'); var normalize = _dereq_('eth-sig-util').normalize; var MetamaskConfig = _dereq_('../config.js'); var MAINNET_RPC = MetamaskConfig.network.mainnet; var ROPSTEN_RPC = MetamaskConfig.network.ropsten; var KOVAN_RPC = MetamaskConfig.network.kovan; var RINKEBY_RPC = MetamaskConfig.network.rinkeby; /* The config-manager is a convenience object * wrapping a pojo-migrator. * * It exists mostly to allow the creation of * convenience methods to access and persist * particular portions of the state. */ module.exports = ConfigManager; function ConfigManager(opts) { // ConfigManager is observable and will emit updates this._subs = []; this.store = opts.store; } ConfigManager.prototype.setConfig = function (config) { var data = this.getData(); data.config = config; this.setData(data); this._emitUpdates(config); }; ConfigManager.prototype.getConfig = function () { var data = this.getData(); return data.config; }; ConfigManager.prototype.setData = function (data) { this.store.putState(data); }; ConfigManager.prototype.getData = function () { return this.store.getState(); }; ConfigManager.prototype.setWallet = function (wallet) { var data = this.getData(); data.wallet = wallet; this.setData(data); }; ConfigManager.prototype.setVault = function (encryptedString) { var data = this.getData(); data.vault = encryptedString; this.setData(data); }; ConfigManager.prototype.getVault = function () { var data = this.getData(); return data.vault; }; ConfigManager.prototype.getKeychains = function () { return this.getData().keychains || []; }; ConfigManager.prototype.setKeychains = function (keychains) { var data = this.getData(); data.keychains = keychains; this.setData(data); }; ConfigManager.prototype.getSelectedAccount = function () { var config = this.getConfig(); return config.selectedAccount; }; ConfigManager.prototype.setSelectedAccount = function (address) { var config = this.getConfig(); config.selectedAccount = ethUtil.addHexPrefix(address); this.setConfig(config); }; ConfigManager.prototype.getWallet = function () { return this.getData().wallet; }; // Takes a boolean ConfigManager.prototype.setShowSeedWords = function (should) { var data = this.getData(); data.showSeedWords = should; this.setData(data); }; ConfigManager.prototype.getShouldShowSeedWords = function () { var data = this.getData(); return data.showSeedWords; }; ConfigManager.prototype.setSeedWords = function (words) { var data = this.getData(); data.seedWords = words; this.setData(data); }; ConfigManager.prototype.getSeedWords = function () { var data = this.getData(); return data.seedWords; }; ConfigManager.prototype.setRpcTarget = function (rpcUrl) { var config = this.getConfig(); config.provider = { type: 'rpc', rpcTarget: rpcUrl }; this.setConfig(config); }; ConfigManager.prototype.setProviderType = function (type) { var config = this.getConfig(); config.provider = { type: type }; this.setConfig(config); }; ConfigManager.prototype.useEtherscanProvider = function () { var config = this.getConfig(); config.provider = { type: 'etherscan' }; this.setConfig(config); }; ConfigManager.prototype.getProvider = function () { var config = this.getConfig(); return config.provider; }; ConfigManager.prototype.getCurrentRpcAddress = function () { var provider = this.getProvider(); if (!provider) return null; switch (provider.type) { case 'mainnet': return MAINNET_RPC; case 'ropsten': return ROPSTEN_RPC; case 'kovan': return KOVAN_RPC; case 'rinkeby': return RINKEBY_RPC; default: return provider && provider.rpcTarget ? provider.rpcTarget : RINKEBY_RPC; } }; // // Tx // ConfigManager.prototype.getTxList = function () { var data = this.getData(); if (data.transactions !== undefined) { return data.transactions; } else { return []; } }; ConfigManager.prototype.setTxList = function (txList) { var data = this.getData(); data.transactions = txList; this.setData(data); }; // wallet nickname methods ConfigManager.prototype.getWalletNicknames = function () { var data = this.getData(); var nicknames = 'walletNicknames' in data ? data.walletNicknames : {}; return nicknames; }; ConfigManager.prototype.nicknameForWallet = function (account) { var address = normalize(account); var nicknames = this.getWalletNicknames(); return nicknames[address]; }; ConfigManager.prototype.setNicknameForWallet = function (account, nickname) { var address = normalize(account); var nicknames = this.getWalletNicknames(); nicknames[address] = nickname; var data = this.getData(); data.walletNicknames = nicknames; this.setData(data); }; // observable ConfigManager.prototype.getSalt = function () { var data = this.getData(); return data.salt; }; ConfigManager.prototype.setSalt = function (salt) { var data = this.getData(); data.salt = salt; this.setData(data); }; ConfigManager.prototype.subscribe = function (fn) { this._subs.push(fn); var unsubscribe = this.unsubscribe.bind(this, fn); return unsubscribe; }; ConfigManager.prototype.unsubscribe = function (fn) { var index = this._subs.indexOf(fn); if (index !== -1) this._subs.splice(index, 1); }; ConfigManager.prototype._emitUpdates = function (state) { this._subs.forEach(function (handler) { handler(state); }); }; ConfigManager.prototype.setLostAccounts = function (lostAccounts) { var data = this.getData(); data.lostAccounts = lostAccounts; this.setData(data); }; ConfigManager.prototype.getLostAccounts = function () { var data = this.getData(); return data.lostAccounts || []; }; },{"../config.js":4,"eth-sig-util":299,"ethereumjs-util":309}],16:[function(_dereq_,module,exports){ 'use strict'; var _keys = _dereq_('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _getPrototypeOf = _dereq_('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = _dereq_('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = _dereq_('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* Ethereum Store * * This module is responsible for tracking any number of accounts * and caching their current balances & transaction counts. * * It also tracks transaction hashes, and checks their inclusion status * on each new block. */ var async = _dereq_('async'); var EthQuery = _dereq_('eth-query'); var ObservableStore = _dereq_('obs-store'); function noop() {} var EthereumStore = function (_ObservableStore) { (0, _inherits3.default)(EthereumStore, _ObservableStore); function EthereumStore() { var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; (0, _classCallCheck3.default)(this, EthereumStore); var _this = (0, _possibleConstructorReturn3.default)(this, (EthereumStore.__proto__ || (0, _getPrototypeOf2.default)(EthereumStore)).call(this, { accounts: {}, transactions: {}, currentBlockNumber: '0', currentBlockHash: '' })); _this._provider = opts.provider; _this._query = new EthQuery(_this._provider); _this._blockTracker = opts.blockTracker; // subscribe to latest block _this._blockTracker.on('block', _this._updateForBlock.bind(_this) // blockTracker.currentBlock may be null );_this._currentBlockNumber = _this._blockTracker.currentBlock; return _this; } // // public // (0, _createClass3.default)(EthereumStore, [{ key: 'addAccount', value: function addAccount(address) { var accounts = this.getState().accounts; accounts[address] = {}; this.updateState({ accounts: accounts }); if (!this._currentBlockNumber) return; this._updateAccount(address); } }, { key: 'removeAccount', value: function removeAccount(address) { var accounts = this.getState().accounts; delete accounts[address]; this.updateState({ accounts: accounts }); } }, { key: 'addTransaction', value: function addTransaction(txHash) { var transactions = this.getState().transactions; transactions[txHash] = {}; this.updateState({ transactions: transactions }); if (!this._currentBlockNumber) return; this._updateTransaction(this._currentBlockNumber, txHash, noop); } }, { key: 'removeTransaction', value: function removeTransaction(txHash) { var transactions = this.getState().transactions; delete transactions[txHash]; this.updateState({ transactions: transactions }); } // // private // }, { key: '_updateForBlock', value: function _updateForBlock(block) { var _this2 = this; var blockNumber = '0x' + block.number.toString('hex'); this._currentBlockNumber = blockNumber; this.updateState({ currentBlockNumber: parseInt(blockNumber) }); this.updateState({ currentBlockHash: '0x' + block.hash.toString('hex') }); async.parallel([this._updateAccounts.bind(this), this._updateTransactions.bind(this, blockNumber)], function (err) { if (err) return console.error(err); _this2.emit('block', _this2.getState()); }); } }, { key: '_updateAccounts', value: function _updateAccounts() { var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : noop; var accounts = this.getState().accounts; var addresses = (0, _keys2.default)(accounts); async.each(addresses, this._updateAccount.bind(this), cb); } }, { key: '_updateAccount', value: function _updateAccount(address) { var _this3 = this; var cb = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; var accounts = this.getState().accounts; this._getAccount(address, function (err, result) { if (err) return cb(err); result.address = address; // only populate if the entry is still present if (accounts[address]) { accounts[address] = result; _this3.updateState({ accounts: accounts }); } cb(null, result); }); } }, { key: '_updateTransactions', value: function _updateTransactions(block) { var cb = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; var transactions = this.getState().transactions; var txHashes = (0, _keys2.default)(transactions); async.each(txHashes, this._updateTransaction.bind(this, block), cb); } }, { key: '_updateTransaction', value: function _updateTransaction(block, txHash) { var _this4 = this; var cb = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : noop; // would use the block here to determine how many confirmations the tx has var transactions = this.getState().transactions; this._query.getTransaction(txHash, function (err, result) { if (err) return cb(err // only populate if the entry is still present );if (transactions[txHash]) { transactions[txHash] = result; _this4.updateState({ transactions: transactions }); } cb(null, result); }); } }, { key: '_getAccount', value: function _getAccount(address) { var cb = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; var query = this._query; async.parallel({ balance: query.getBalance.bind(query, address), nonce: query.getTransactionCount.bind(query, address), code: query.getCode.bind(query, address) }, cb); } }]); return EthereumStore; }(ObservableStore); module.exports = EthereumStore; },{"async":77,"babel-runtime/core-js/object/get-prototype-of":84,"babel-runtime/core-js/object/keys":85,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"babel-runtime/helpers/inherits":93,"babel-runtime/helpers/possibleConstructorReturn":94,"eth-query":298,"obs-store":384}],17:[function(_dereq_,module,exports){ (function (Buffer){ 'use strict'; var _keys = _dereq_('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _getPrototypeOf = _dereq_('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = _dereq_('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = _dereq_('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var EventEmitter = _dereq_('events'); var ObservableStore = _dereq_('obs-store'); var ethUtil = _dereq_('ethereumjs-util'); var createId = _dereq_('./random-id'); module.exports = function (_EventEmitter) { (0, _inherits3.default)(MessageManager, _EventEmitter); function MessageManager(opts) { (0, _classCallCheck3.default)(this, MessageManager); var _this = (0, _possibleConstructorReturn3.default)(this, (MessageManager.__proto__ || (0, _getPrototypeOf2.default)(MessageManager)).call(this)); _this.memStore = new ObservableStore({ unapprovedMsgs: {}, unapprovedMsgCount: 0 }); _this.messages = []; return _this; } (0, _createClass3.default)(MessageManager, [{ key: 'getUnapprovedMsgs', value: function getUnapprovedMsgs() { return this.messages.filter(function (msg) { return msg.status === 'unapproved'; }).reduce(function (result, msg) { result[msg.id] = msg;return result; }, {}); } }, { key: 'addUnapprovedMessage', value: function addUnapprovedMessage(msgParams) { msgParams.data = normalizeMsgData(msgParams.data // create txData obj with parameters and meta data );var time = new Date().getTime(); var msgId = createId(); var msgData = { id: msgId, msgParams: msgParams, time: time, status: 'unapproved', type: 'eth_sign' }; this.addMsg(msgData // signal update );this.emit('update'); return msgId; } }, { key: 'addMsg', value: function addMsg(msg) { this.messages.push(msg); this._saveMsgList(); } }, { key: 'getMsg', value: function getMsg(msgId) { return this.messages.find(function (msg) { return msg.id === msgId; }); } }, { key: 'approveMessage', value: function approveMessage(msgParams) { this.setMsgStatusApproved(msgParams.metamaskId); return this.prepMsgForSigning(msgParams); } }, { key: 'setMsgStatusApproved', value: function setMsgStatusApproved(msgId) { this._setMsgStatus(msgId, 'approved'); } }, { key: 'setMsgStatusSigned', value: function setMsgStatusSigned(msgId, rawSig) { var msg = this.getMsg(msgId); msg.rawSig = rawSig; this._updateMsg(msg); this._setMsgStatus(msgId, 'signed'); } }, { key: 'prepMsgForSigning', value: function prepMsgForSigning(msgParams) { delete msgParams.metamaskId; return _promise2.default.resolve(msgParams); } }, { key: 'rejectMsg', value: function rejectMsg(msgId) { this._setMsgStatus(msgId, 'rejected'); } // // PRIVATE METHODS // }, { key: '_setMsgStatus', value: function _setMsgStatus(msgId, status) { var msg = this.getMsg(msgId); if (!msg) throw new Error('MessageManager - Message not found for id: "${msgId}".'); msg.status = status; this._updateMsg(msg); this.emit(msgId + ':' + status, msg); if (status === 'rejected' || status === 'signed') { this.emit(msgId + ':finished', msg); } } }, { key: '_updateMsg', value: function _updateMsg(msg) { var index = this.messages.findIndex(function (message) { return message.id === msg.id; }); if (index !== -1) { this.messages[index] = msg; } this._saveMsgList(); } }, { key: '_saveMsgList', value: function _saveMsgList() { var unapprovedMsgs = this.getUnapprovedMsgs(); var unapprovedMsgCount = (0, _keys2.default)(unapprovedMsgs).length; this.memStore.updateState({ unapprovedMsgs: unapprovedMsgs, unapprovedMsgCount: unapprovedMsgCount }); this.emit('updateBadge'); } }, { key: 'unapprovedMsgCount', get: function get() { return (0, _keys2.default)(this.getUnapprovedMsgs()).length; } }]); return MessageManager; }(EventEmitter); function normalizeMsgData(data) { if (data.slice(0, 2) === '0x') { // data is already hex return data; } else { // data is unicode, convert to hex return ethUtil.bufferToHex(new Buffer(data, 'utf8')); } } }).call(this,_dereq_("buffer").Buffer) },{"./random-id":24,"babel-runtime/core-js/object/get-prototype-of":84,"babel-runtime/core-js/object/keys":85,"babel-runtime/core-js/promise":87,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"babel-runtime/helpers/inherits":93,"babel-runtime/helpers/possibleConstructorReturn":94,"buffer":142,"ethereumjs-util":309,"events":314,"obs-store":384}],18:[function(_dereq_,module,exports){ 'use strict'; var _regenerator = _dereq_('babel-runtime/regenerator'); var _regenerator2 = _interopRequireDefault(_regenerator); var _asyncToGenerator2 = _dereq_('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var Migrator = function () { function Migrator() { var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; (0, _classCallCheck3.default)(this, Migrator); var migrations = opts.migrations || []; // sort migrations by version this.migrations = migrations.sort(function (a, b) { return a.version - b.version; } // grab migration with highest version );var lastMigration = this.migrations.slice(-1)[0]; // use specified defaultVersion or highest migration version this.defaultVersion = opts.defaultVersion || lastMigration && lastMigration.version || 0; } // run all pending migrations on meta in place (0, _createClass3.default)(Migrator, [{ key: 'migrateData', value: function () { var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee() { var versionedData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.generateInitialState(); var pendingMigrations, index, migration, migrationIsPending; return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: migrationIsPending = function migrationIsPending(migration) { return migration.version > versionedData.meta.version; }; pendingMigrations = this.migrations.filter(migrationIsPending); _context.t0 = _regenerator2.default.keys(pendingMigrations); case 3: if ((_context.t1 = _context.t0()).done) { _context.next = 15; break; } index = _context.t1.value; migration = pendingMigrations[index]; _context.next = 8; return migration.migrate(versionedData); case 8: versionedData = _context.sent; if (versionedData.data) { _context.next = 11; break; } throw new Error('Migrator - migration returned empty data'); case 11: if (!(versionedData.version !== undefined && versionedData.meta.version !== migration.version)) { _context.next = 13; break; } throw new Error('Migrator - Migration did not update version number correctly'); case 13: _context.next = 3; break; case 15: return _context.abrupt('return', versionedData); case 16: case 'end': return _context.stop(); } } }, _callee, this); })); function migrateData() { return _ref.apply(this, arguments); } return migrateData; }() }, { key: 'generateInitialState', value: function generateInitialState(initState) { return { meta: { version: this.defaultVersion }, data: initState }; } }]); return Migrator; }(); module.exports = Migrator; },{"babel-runtime/helpers/asyncToGenerator":90,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"babel-runtime/regenerator":96}],19:[function(_dereq_,module,exports){ 'use strict'; module.exports = function (promiseFn) { return function () { var args = []; for (var i = 0; i < arguments.length - 1; i++) { args.push(arguments[i]); } var cb = arguments[arguments.length - 1]; var nodeified = promiseFn.apply(this, args); if (!nodeified) { var methodName = String(promiseFn).split('(')[0]; throw new Error('The ' + methodName + ' did not return a Promise, but was nodeified.'); } nodeified.then(function (result) { cb(null, result); }).catch(function (reason) { cb(reason); }); return nodeified; }; }; },{}],20:[function(_dereq_,module,exports){ 'use strict'; var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var extension = _dereq_('extensionizer'); var height = 520; var width = 360; var NotificationManager = function () { function NotificationManager() { (0, _classCallCheck3.default)(this, NotificationManager); } (0, _createClass3.default)(NotificationManager, [{ key: 'showPopup', // // Public // value: function showPopup() { this._getPopup(function (err, popup) { if (err) throw err; if (popup) { // bring focus to existing popup extension.windows.update(popup.id, { focused: true }); } else { // create new popup extension.windows.create({ url: 'notification.html', type: 'popup', width: width, height: height }); } }); } }, { key: 'closePopup', value: function closePopup() { this._getPopup(function (err, popup) { if (err) throw err; if (!popup) return; extension.windows.remove(popup.id, console.error); }); } // // Private // }, { key: '_getPopup', value: function _getPopup(cb) { var _this = this; this._getWindows(function (err, windows) { if (err) throw err; cb(null, _this._getPopupIn(windows)); }); } }, { key: '_getWindows', value: function _getWindows(cb) { // Ignore in test environment if (!extension.windows) { return cb(); } extension.windows.getAll({}, function (windows) { cb(null, windows); }); } }, { key: '_getPopupIn', value: function _getPopupIn(windows) { return windows ? windows.find(function (win) { return win && win.type === 'popup' && win.height === height && win.width === width; }) : null; } }]); return NotificationManager; }(); module.exports = NotificationManager; },{"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"extensionizer":317}],21:[function(_dereq_,module,exports){ 'use strict'; var through = _dereq_('through2'); module.exports = ObjectMultiplex; function ObjectMultiplex(opts) { opts = opts || {}; // create multiplexer var mx = through.obj(function (chunk, enc, cb) { var name = chunk.name; var data = chunk.data; var substream = mx.streams[name]; if (!substream) { console.warn('orphaned data for stream "' + name + '"'); } else { if (substream.push) substream.push(data); } return cb(); }); mx.streams = {}; // create substreams mx.createStream = function (name) { var substream = mx.streams[name] = through.obj(function (chunk, enc, cb) { mx.push({ name: name, data: chunk }); return cb(); }); mx.on('end', function () { return substream.emit('end'); }); if (opts.error) { mx.on('error', function () { return substream.emit('error'); }); } return substream; }; // ignore streams (dont display orphaned data warning) mx.ignoreStream = function (name) { mx.streams[name] = true; }; return mx; } },{"through2":458}],22:[function(_dereq_,module,exports){ (function (Buffer){ 'use strict'; var _keys = _dereq_('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _stringify = _dereq_('babel-runtime/core-js/json/stringify'); var _stringify2 = _interopRequireDefault(_stringify); var _getPrototypeOf = _dereq_('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = _dereq_('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = _dereq_('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var EventEmitter = _dereq_('events'); var ObservableStore = _dereq_('obs-store'); var ethUtil = _dereq_('ethereumjs-util'); var createId = _dereq_('./random-id'); var hexRe = /^[0-9A-Fa-f]+$/g; module.exports = function (_EventEmitter) { (0, _inherits3.default)(PersonalMessageManager, _EventEmitter); function PersonalMessageManager(opts) { (0, _classCallCheck3.default)(this, PersonalMessageManager); var _this = (0, _possibleConstructorReturn3.default)(this, (PersonalMessageManager.__proto__ || (0, _getPrototypeOf2.default)(PersonalMessageManager)).call(this)); _this.memStore = new ObservableStore({ unapprovedPersonalMsgs: {}, unapprovedPersonalMsgCount: 0 }); _this.messages = []; return _this; } (0, _createClass3.default)(PersonalMessageManager, [{ key: 'getUnapprovedMsgs', value: function getUnapprovedMsgs() { return this.messages.filter(function (msg) { return msg.status === 'unapproved'; }).reduce(function (result, msg) { result[msg.id] = msg;return result; }, {}); } }, { key: 'addUnapprovedMessage', value: function addUnapprovedMessage(msgParams) { log.debug('PersonalMessageManager addUnapprovedMessage: ' + (0, _stringify2.default)(msgParams)); msgParams.data = this.normalizeMsgData(msgParams.data // create txData obj with parameters and meta data );var time = new Date().getTime(); var msgId = createId(); var msgData = { id: msgId, msgParams: msgParams, time: time, status: 'unapproved', type: 'personal_sign' }; this.addMsg(msgData // signal update );this.emit('update'); return msgId; } }, { key: 'addMsg', value: function addMsg(msg) { this.messages.push(msg); this._saveMsgList(); } }, { key: 'getMsg', value: function getMsg(msgId) { return this.messages.find(function (msg) { return msg.id === msgId; }); } }, { key: 'approveMessage', value: function approveMessage(msgParams) { this.setMsgStatusApproved(msgParams.metamaskId); return this.prepMsgForSigning(msgParams); } }, { key: 'setMsgStatusApproved', value: function setMsgStatusApproved(msgId) { this._setMsgStatus(msgId, 'approved'); } }, { key: 'setMsgStatusSigned', value: function setMsgStatusSigned(msgId, rawSig) { var msg = this.getMsg(msgId); msg.rawSig = rawSig; this._updateMsg(msg); this._setMsgStatus(msgId, 'signed'); } }, { key: 'prepMsgForSigning', value: function prepMsgForSigning(msgParams) { delete msgParams.metamaskId; return _promise2.default.resolve(msgParams); } }, { key: 'rejectMsg', value: function rejectMsg(msgId) { this._setMsgStatus(msgId, 'rejected'); } // // PRIVATE METHODS // }, { key: '_setMsgStatus', value: function _setMsgStatus(msgId, status) { var msg = this.getMsg(msgId); if (!msg) throw new Error('PersonalMessageManager - Message not found for id: "${msgId}".'); msg.status = status; this._updateMsg(msg); this.emit(msgId + ':' + status, msg); if (status === 'rejected' || status === 'signed') { this.emit(msgId + ':finished', msg); } } }, { key: '_updateMsg', value: function _updateMsg(msg) { var index = this.messages.findIndex(function (message) { return message.id === msg.id; }); if (index !== -1) { this.messages[index] = msg; } this._saveMsgList(); } }, { key: '_saveMsgList', value: function _saveMsgList() { var unapprovedPersonalMsgs = this.getUnapprovedMsgs(); var unapprovedPersonalMsgCount = (0, _keys2.default)(unapprovedPersonalMsgs).length; this.memStore.updateState({ unapprovedPersonalMsgs: unapprovedPersonalMsgs, unapprovedPersonalMsgCount: unapprovedPersonalMsgCount }); this.emit('updateBadge'); } }, { key: 'normalizeMsgData', value: function normalizeMsgData(data) { try { var stripped = ethUtil.stripHexPrefix(data); if (stripped.match(hexRe)) { return ethUtil.addHexPrefix(stripped); } } catch (e) { log.debug('Message was not hex encoded, interpreting as utf8.'); } return ethUtil.bufferToHex(new Buffer(data, 'utf8')); } }, { key: 'unapprovedPersonalMsgCount', get: function get() { return (0, _keys2.default)(this.getUnapprovedMsgs()).length; } }]); return PersonalMessageManager; }(EventEmitter); }).call(this,_dereq_("buffer").Buffer) },{"./random-id":24,"babel-runtime/core-js/json/stringify":78,"babel-runtime/core-js/object/get-prototype-of":84,"babel-runtime/core-js/object/keys":85,"babel-runtime/core-js/promise":87,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"babel-runtime/helpers/inherits":93,"babel-runtime/helpers/possibleConstructorReturn":94,"buffer":142,"ethereumjs-util":309,"events":314,"obs-store":384}],23:[function(_dereq_,module,exports){ (function (Buffer){ 'use strict'; var Duplex = _dereq_('readable-stream').Duplex; var inherits = _dereq_('util').inherits; module.exports = PortDuplexStream; inherits(PortDuplexStream, Duplex); function PortDuplexStream(port) { Duplex.call(this, { objectMode: true }); this._port = port; port.onMessage.addListener(this._onMessage.bind(this)); port.onDisconnect.addListener(this._onDisconnect.bind(this)); } // private PortDuplexStream.prototype._onMessage = function (msg) { if (Buffer.isBuffer(msg)) { delete msg._isBuffer; var data = new Buffer(msg); // console.log('PortDuplexStream - saw message as buffer', data) this.push(data); } else { // console.log('PortDuplexStream - saw message', msg) this.push(msg); } }; PortDuplexStream.prototype._onDisconnect = function () { try { this.push(null); } catch (err) { this.emit('error', err); } }; // stream plumbing PortDuplexStream.prototype._read = noop; PortDuplexStream.prototype._write = function (msg, encoding, cb) { try { if (Buffer.isBuffer(msg)) { var data = msg.toJSON(); data._isBuffer = true; // console.log('PortDuplexStream - sent message as buffer', data) this._port.postMessage(data); } else { // console.log('PortDuplexStream - sent message', msg) this._port.postMessage(msg); } } catch (err) { // console.error(err) return cb(new Error('PortDuplexStream - disconnected')); } cb(); }; // util function noop() {} }).call(this,_dereq_("buffer").Buffer) },{"buffer":142,"readable-stream":429,"util":468}],24:[function(_dereq_,module,exports){ "use strict"; var _maxSafeInteger = _dereq_("babel-runtime/core-js/number/max-safe-integer"); var _maxSafeInteger2 = _interopRequireDefault(_maxSafeInteger); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var MAX = _maxSafeInteger2.default; var idCounter = Math.round(Math.random() * MAX); function createRandomId() { idCounter = idCounter % MAX; return idCounter++; } module.exports = createRandomId; },{"babel-runtime/core-js/number/max-safe-integer":80}],25:[function(_dereq_,module,exports){ 'use strict'; var _stringify = _dereq_('babel-runtime/core-js/json/stringify'); var _stringify2 = _interopRequireDefault(_stringify); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var Through = _dereq_('through2'); var endOfStream = _dereq_('end-of-stream'); var ObjectMultiplex = _dereq_('./obj-multiplex'); module.exports = { jsonParseStream: jsonParseStream, jsonStringifyStream: jsonStringifyStream, setupMultiplex: setupMultiplex }; function jsonParseStream() { return Through.obj(function (serialized, encoding, cb) { this.push(JSON.parse(serialized)); cb(); }); } function jsonStringifyStream() { return Through.obj(function (obj, encoding, cb) { this.push((0, _stringify2.default)(obj)); cb(); }); } function setupMultiplex(connectionStream) { var mx = ObjectMultiplex(); connectionStream.pipe(mx).pipe(connectionStream); endOfStream(mx, function (err) { if (err) console.error(err); }); endOfStream(connectionStream, function (err) { if (err) console.error(err); mx.destroy(); }); return mx; } },{"./obj-multiplex":21,"babel-runtime/core-js/json/stringify":78,"end-of-stream":291,"through2":458}],26:[function(_dereq_,module,exports){ 'use strict'; var _stringify = _dereq_('babel-runtime/core-js/json/stringify'); var _stringify2 = _interopRequireDefault(_stringify); var _assign = _dereq_('babel-runtime/core-js/object/assign'); var _assign2 = _interopRequireDefault(_assign); var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var async = _dereq_('async'); var ethUtil = _dereq_('ethereumjs-util'); var Transaction = _dereq_('ethereumjs-tx'); var normalize = _dereq_('eth-sig-util').normalize; var BN = ethUtil.BN; /* tx-utils are utility methods for Transaction manager its passed ethquery and used to do things like calculate gas of a tx. */ module.exports = function () { function txProviderUtils(ethQuery) { (0, _classCallCheck3.default)(this, txProviderUtils); this.query = ethQuery; } (0, _createClass3.default)(txProviderUtils, [{ key: 'analyzeGasUsage', value: function analyzeGasUsage(txMeta, cb) { var self = this; this.query.getBlockByNumber('latest', true, function (err, block) { if (err) return cb(err); async.waterfall([self.setBlockGasLimit.bind(self, txMeta, block.gasLimit), self.estimateTxGas.bind(self, txMeta, block.gasLimit), self.setTxGas.bind(self, txMeta, block.gasLimit)], cb); }); } }, { key: 'setBlockGasLimit', value: function setBlockGasLimit(txMeta, blockGasLimitHex, cb) { var blockGasLimitBN = hexToBn(blockGasLimitHex); var saferGasLimitBN = BnMultiplyByFraction(blockGasLimitBN, 19, 20); txMeta.blockGasLimit = bnToHex(saferGasLimitBN); cb(); return; } }, { key: 'estimateTxGas', value: function estimateTxGas(txMeta, blockGasLimitHex, cb) { var txParams = txMeta.txParams; // check if gasLimit is already specified txMeta.gasLimitSpecified = Boolean(txParams.gas // if not, fallback to block gasLimit );if (!txMeta.gasLimitSpecified) { var blockGasLimitBN = hexToBn(blockGasLimitHex); var saferGasLimitBN = BnMultiplyByFraction(blockGasLimitBN, 19, 20); txParams.gas = bnToHex(saferGasLimitBN); } // run tx, see if it will OOG this.query.estimateGas(txParams, cb); } }, { key: 'setTxGas', value: function setTxGas(txMeta, blockGasLimitHex, estimatedGasHex, cb) { txMeta.estimatedGas = estimatedGasHex; var txParams = txMeta.txParams; // if gasLimit was specified and doesnt OOG, // use original specified amount if (txMeta.gasLimitSpecified) { txMeta.estimatedGas = txParams.gas; cb(); return; } // if gasLimit not originally specified, // try adding an additional gas buffer to our estimation for safety var recommendedGasHex = this.addGasBuffer(txMeta.estimatedGas, blockGasLimitHex); txParams.gas = recommendedGasHex; cb(); return; } }, { key: 'addGasBuffer', value: function addGasBuffer(initialGasLimitHex, blockGasLimitHex) { var initialGasLimitBn = hexToBn(initialGasLimitHex); var blockGasLimitBn = hexToBn(blockGasLimitHex); var upperGasLimitBn = blockGasLimitBn.muln(0.9); var bufferedGasLimitBn = initialGasLimitBn.muln(1.5 // if initialGasLimit is above blockGasLimit, dont modify it );if (initialGasLimitBn.gt(upperGasLimitBn)) return bnToHex(initialGasLimitBn // if bufferedGasLimit is below blockGasLimit, use bufferedGasLimit );if (bufferedGasLimitBn.lt(upperGasLimitBn)) return bnToHex(bufferedGasLimitBn // otherwise use blockGasLimit );return bnToHex(upperGasLimitBn); } }, { key: 'fillInTxParams', value: function fillInTxParams(txParams, cb) { var _this = this; var fromAddress = txParams.from; var reqs = {}; if (isUndef(txParams.gas)) reqs.gas = function (cb) { return _this.query.estimateGas(txParams, cb); }; if (isUndef(txParams.gasPrice)) reqs.gasPrice = function (cb) { return _this.query.gasPrice(cb); }; if (isUndef(txParams.nonce)) reqs.nonce = function (cb) { return _this.query.getTransactionCount(fromAddress, 'pending', cb); }; async.parallel(reqs, function (err, result) { if (err) return cb(err // write results to txParams obj );(0, _assign2.default)(txParams, result); cb(); }); } // builds ethTx from txParams object }, { key: 'buildEthTxFromParams', value: function buildEthTxFromParams(txParams) { // normalize values txParams.to = normalize(txParams.to); txParams.from = normalize(txParams.from); txParams.value = normalize(txParams.value); txParams.data = normalize(txParams.data); txParams.gas = normalize(txParams.gas || txParams.gasLimit); txParams.gasPrice = normalize(txParams.gasPrice); txParams.nonce = normalize(txParams.nonce // build ethTx );log.info('Prepared tx for signing: ' + (0, _stringify2.default)(txParams)); var ethTx = new Transaction(txParams); return ethTx; } }, { key: 'publishTransaction', value: function publishTransaction(rawTx, cb) { this.query.sendRawTransaction(rawTx, cb); } }, { key: 'validateTxParams', value: function validateTxParams(txParams, cb) { if ('value' in txParams && txParams.value.indexOf('-') === 0) { cb(new Error('Invalid transaction value of ' + txParams.value + ' not a positive number.')); } else { cb(); } } }]); return txProviderUtils; }(); // util function isUndef(value) { return value === undefined; } function bnToHex(inputBn) { return ethUtil.addHexPrefix(inputBn.toString(16)); } function hexToBn(inputHex) { return new BN(ethUtil.stripHexPrefix(inputHex), 16); } function BnMultiplyByFraction(targetBN, numerator, denominator) { var numBN = new BN(numerator); var denomBN = new BN(denominator); return targetBN.mul(numBN).div(denomBN); } },{"async":77,"babel-runtime/core-js/json/stringify":78,"babel-runtime/core-js/object/assign":81,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"eth-sig-util":299,"ethereumjs-tx":306,"ethereumjs-util":309}],27:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _stringify = _dereq_('babel-runtime/core-js/json/stringify'); var _stringify2 = _interopRequireDefault(_stringify); var _getPrototypeOf = _dereq_('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = _dereq_('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = _dereq_('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var EventEmitter = _dereq_('events'); var extend = _dereq_('xtend'); var promiseToCallback = _dereq_('promise-to-callback'); var pipe = _dereq_('pump'); var Dnode = _dereq_('dnode'); var ObservableStore = _dereq_('obs-store'); var EthStore = _dereq_('./lib/eth-store'); var EthQuery = _dereq_('eth-query'); var streamIntoProvider = _dereq_('web3-stream-provider/handler'); var setupMultiplex = _dereq_('./lib/stream-utils.js').setupMultiplex; var KeyringController = _dereq_('./keyring-controller'); var NetworkController = _dereq_('./controllers/network'); var PreferencesController = _dereq_('./controllers/preferences'); var CurrencyController = _dereq_('./controllers/currency'); var NoticeController = _dereq_('./notice-controller'); var ShapeShiftController = _dereq_('./controllers/shapeshift'); var AddressBookController = _dereq_('./controllers/address-book'); var MessageManager = _dereq_('./lib/message-manager'); var PersonalMessageManager = _dereq_('./lib/personal-message-manager'); var TransactionController = _dereq_('./controllers/transactions'); var ConfigManager = _dereq_('./lib/config-manager'); var autoFaucet = _dereq_('./lib/auto-faucet'); var nodeify = _dereq_('./lib/nodeify'); var accountImporter = _dereq_('./account-import-strategies'); var getBuyEthUrl = _dereq_('./lib/buy-eth-url'); var version = _dereq_('../manifest.json').version; module.exports = function (_EventEmitter) { (0, _inherits3.default)(MetamaskController, _EventEmitter); function MetamaskController(opts) { (0, _classCallCheck3.default)(this, MetamaskController); var _this = (0, _possibleConstructorReturn3.default)(this, (MetamaskController.__proto__ || (0, _getPrototypeOf2.default)(MetamaskController)).call(this)); _this.opts = opts; var initState = opts.initState || {}; // platform-specific api _this.platform = opts.platform; // observable state store _this.store = new ObservableStore(initState); // network store _this.networkController = new NetworkController(initState.NetworkController); // config manager _this.configManager = new ConfigManager({ store: _this.store }); // preferences controller _this.preferencesController = new PreferencesController({ initState: initState.PreferencesController }); // currency controller _this.currencyController = new CurrencyController({ initState: initState.CurrencyController }); _this.currencyController.updateConversionRate(); _this.currencyController.scheduleConversionInterval // rpc provider ();_this.provider = _this.initializeProvider // eth data query tools ();_this.ethQuery = new EthQuery(_this.provider); _this.ethStore = new EthStore({ provider: _this.provider, blockTracker: _this.provider }); // key mgmt _this.keyringController = new KeyringController({ initState: initState.KeyringController, ethStore: _this.ethStore, getNetwork: _this.networkController.getNetworkState.bind(_this.networkController) }); _this.keyringController.on('newAccount', function (address) { _this.preferencesController.setSelectedAddress(address); }); _this.keyringController.on('newVault', function (address) { autoFaucet(address); } // address book controller );_this.addressBookController = new AddressBookController({ initState: initState.AddressBookController }, _this.keyringController); // tx mgmt _this.txController = new TransactionController({ initState: initState.TransactionController || initState.TransactionManager, networkStore: _this.networkController.networkStore, preferencesStore: _this.preferencesController.store, txHistoryLimit: 40, getNetwork: _this.networkController.getNetworkState.bind(_this), signTransaction: _this.keyringController.signTransaction.bind(_this.keyringController), provider: _this.provider, blockTracker: _this.provider, ethQuery: _this.ethQuery }); // notices _this.noticeController = new NoticeController({ initState: initState.NoticeController }); _this.noticeController.updateNoticesList // to be uncommented when retrieving notices from a remote server. // this.noticeController.startPolling() ();_this.shapeshiftController = new ShapeShiftController({ initState: initState.ShapeShiftController }); _this.networkController.lookupNetwork(); _this.messageManager = new MessageManager(); _this.personalMessageManager = new PersonalMessageManager(); _this.publicConfigStore = _this.initPublicConfigStore // manual disk state subscriptions ();_this.txController.store.subscribe(function (state) { _this.store.updateState({ TransactionController: state }); }); _this.keyringController.store.subscribe(function (state) { _this.store.updateState({ KeyringController: state }); }); _this.preferencesController.store.subscribe(function (state) { _this.store.updateState({ PreferencesController: state }); }); _this.addressBookController.store.subscribe(function (state) { _this.store.updateState({ AddressBookController: state }); }); _this.currencyController.store.subscribe(function (state) { _this.store.updateState({ CurrencyController: state }); }); _this.noticeController.store.subscribe(function (state) { _this.store.updateState({ NoticeController: state }); }); _this.shapeshiftController.store.subscribe(function (state) { _this.store.updateState({ ShapeShiftController: state }); }); _this.networkController.store.subscribe(function (state) { _this.store.updateState({ NetworkController: state }); } // manual mem state subscriptions );_this.networkController.store.subscribe(_this.sendUpdate.bind(_this)); _this.ethStore.subscribe(_this.sendUpdate.bind(_this)); _this.txController.memStore.subscribe(_this.sendUpdate.bind(_this)); _this.messageManager.memStore.subscribe(_this.sendUpdate.bind(_this)); _this.personalMessageManager.memStore.subscribe(_this.sendUpdate.bind(_this)); _this.keyringController.memStore.subscribe(_this.sendUpdate.bind(_this)); _this.preferencesController.store.subscribe(_this.sendUpdate.bind(_this)); _this.addressBookController.store.subscribe(_this.sendUpdate.bind(_this)); _this.currencyController.store.subscribe(_this.sendUpdate.bind(_this)); _this.noticeController.memStore.subscribe(_this.sendUpdate.bind(_this)); _this.shapeshiftController.store.subscribe(_this.sendUpdate.bind(_this)); return _this; } // // Constructor helpers // (0, _createClass3.default)(MetamaskController, [{ key: 'initializeProvider', value: function initializeProvider() { var _this2 = this; return this.networkController.initializeProvider({ static: { eth_syncing: false, web3_clientVersion: 'MetaMask/v' + version }, rpcUrl: this.networkController.getCurrentRpcAddress(), // account mgmt getAccounts: function getAccounts(cb) { var isUnlocked = _this2.keyringController.memStore.getState().isUnlocked; var result = []; var selectedAddress = _this2.preferencesController.getSelectedAddress // only show address if account is unlocked ();if (isUnlocked && selectedAddress) { result.push(selectedAddress); } cb(null, result); }, // tx signing processTransaction: function processTransaction(txParams, cb) { return _this2.newUnapprovedTransaction(txParams, cb); }, // old style msg signing processMessage: this.newUnsignedMessage.bind(this), // new style msg signing processPersonalMessage: this.newUnsignedPersonalMessage.bind(this) }); } }, { key: 'initPublicConfigStore', value: function initPublicConfigStore() { // get init state var publicConfigStore = new ObservableStore(); // memStore -> transform -> publicConfigStore this.on('update', function (memState) { var publicState = selectPublicState(memState); publicConfigStore.putState(publicState); }); function selectPublicState(memState) { var result = { selectedAddress: memState.isUnlocked ? memState.selectedAddress : undefined, networkVersion: memState.network }; return result; } return publicConfigStore; } // // State Management // }, { key: 'getState', value: function getState() { var wallet = this.configManager.getWallet(); var vault = this.keyringController.store.getState().vault; var isInitialized = !!wallet || !!vault; return extend({ isInitialized: isInitialized }, this.networkController.store.getState(), this.ethStore.getState(), this.txController.memStore.getState(), this.messageManager.memStore.getState(), this.personalMessageManager.memStore.getState(), this.keyringController.memStore.getState(), this.preferencesController.store.getState(), this.addressBookController.store.getState(), this.currencyController.store.getState(), this.noticeController.memStore.getState(), // config manager this.configManager.getConfig(), this.shapeshiftController.store.getState(), { lostAccounts: this.configManager.getLostAccounts(), seedWords: this.configManager.getSeedWords() }); } // // Remote Features // }, { key: 'getApi', value: function getApi() { var _this3 = this; var keyringController = this.keyringController; var preferencesController = this.preferencesController; var txController = this.txController; var noticeController = this.noticeController; var addressBookController = this.addressBookController; return { // etc getState: function getState(cb) { return cb(null, _this3.getState()); }, setProviderType: this.networkController.setProviderType.bind(this.networkController), setCurrentCurrency: this.setCurrentCurrency.bind(this), markAccountsFound: this.markAccountsFound.bind(this), // coinbase buyEth: this.buyEth.bind(this), // shapeshift createShapeShiftTx: this.createShapeShiftTx.bind(this), // primary HD keyring management addNewAccount: this.addNewAccount.bind(this), placeSeedWords: this.placeSeedWords.bind(this), clearSeedWordCache: this.clearSeedWordCache.bind(this), importAccountWithStrategy: this.importAccountWithStrategy.bind(this), // vault management submitPassword: this.submitPassword.bind(this), // PreferencesController setSelectedAddress: nodeify(preferencesController.setSelectedAddress).bind(preferencesController), setDefaultRpc: nodeify(this.setDefaultRpc).bind(this), setCustomRpc: nodeify(this.setCustomRpc).bind(this), // AddressController setAddressBook: nodeify(addressBookController.setAddressBook).bind(addressBookController), // KeyringController setLocked: nodeify(keyringController.setLocked).bind(keyringController), createNewVaultAndKeychain: nodeify(keyringController.createNewVaultAndKeychain).bind(keyringController), createNewVaultAndRestore: nodeify(keyringController.createNewVaultAndRestore).bind(keyringController), addNewKeyring: nodeify(keyringController.addNewKeyring).bind(keyringController), saveAccountLabel: nodeify(keyringController.saveAccountLabel).bind(keyringController), exportAccount: nodeify(keyringController.exportAccount).bind(keyringController), // txController approveTransaction: txController.approveTransaction.bind(txController), cancelTransaction: txController.cancelTransaction.bind(txController), updateAndApproveTransaction: this.updateAndApproveTx.bind(this), // messageManager signMessage: nodeify(this.signMessage).bind(this), cancelMessage: this.cancelMessage.bind(this), // personalMessageManager signPersonalMessage: nodeify(this.signPersonalMessage).bind(this), cancelPersonalMessage: this.cancelPersonalMessage.bind(this), // notices checkNotices: noticeController.updateNoticesList.bind(noticeController), markNoticeRead: noticeController.markNoticeRead.bind(noticeController) }; } }, { key: 'setupUntrustedCommunication', value: function setupUntrustedCommunication(connectionStream, originDomain) { // setup multiplexing var mx = setupMultiplex(connectionStream // connect features );this.setupProviderConnection(mx.createStream('provider'), originDomain); this.setupPublicConfig(mx.createStream('publicConfig')); } }, { key: 'setupTrustedCommunication', value: function setupTrustedCommunication(connectionStream, originDomain) { // setup multiplexing var mx = setupMultiplex(connectionStream // connect features );this.setupControllerConnection(mx.createStream('controller')); this.setupProviderConnection(mx.createStream('provider'), originDomain); } }, { key: 'setupControllerConnection', value: function setupControllerConnection(outStream) { var _this4 = this; var api = this.getApi(); var dnode = Dnode(api); outStream.pipe(dnode).pipe(outStream); dnode.on('remote', function (remote) { // push updates to popup var sendUpdate = remote.sendUpdate.bind(remote); _this4.on('update', sendUpdate); }); } }, { key: 'setupProviderConnection', value: function setupProviderConnection(outStream, originDomain) { streamIntoProvider(outStream, this.provider, logger); function logger(err, request, response) { if (err) return console.error(err); if (response.error) { console.error('Error in RPC response:\n', response.error); } if (request.isMetamaskInternal) return; log.info('RPC (' + originDomain + '):', request, '->', response); } } }, { key: 'setupPublicConfig', value: function setupPublicConfig(outStream) { pipe(this.publicConfigStore, outStream); } }, { key: 'sendUpdate', value: function sendUpdate() { this.emit('update', this.getState()); } // // Vault Management // }, { key: 'submitPassword', value: function submitPassword(password, cb) { return this.keyringController.submitPassword(password).then(function (newState) { cb(null, newState); }).catch(function (reason) { cb(reason); }); } // // Opinionated Keyring Management // }, { key: 'addNewAccount', value: function addNewAccount(cb) { var primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0]; if (!primaryKeyring) return cb(new Error('MetamaskController - No HD Key Tree found')); promiseToCallback(this.keyringController.addNewAccount(primaryKeyring))(cb); } // Adds the current vault's seed words to the UI's state tree. // // Used when creating a first vault, to allow confirmation. // Also used when revealing the seed words in the confirmation view. }, { key: 'placeSeedWords', value: function placeSeedWords(cb) { var _this5 = this; var primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0]; if (!primaryKeyring) return cb(new Error('MetamaskController - No HD Key Tree found')); primaryKeyring.serialize().then(function (serialized) { var seedWords = serialized.mnemonic; _this5.configManager.setSeedWords(seedWords); cb(null, seedWords); }); } // ClearSeedWordCache // // Removes the primary account's seed words from the UI's state tree, // ensuring they are only ever available in the background process. }, { key: 'clearSeedWordCache', value: function clearSeedWordCache(cb) { this.configManager.setSeedWords(null); cb(null, this.preferencesController.getSelectedAddress()); } }, { key: 'importAccountWithStrategy', value: function importAccountWithStrategy(strategy, args, cb) { var _this6 = this; accountImporter.importAccount(strategy, args).then(function (privateKey) { return _this6.keyringController.addNewKeyring('Simple Key Pair', [privateKey]); }).then(function (keyring) { return keyring.getAccounts(); }).then(function (accounts) { return _this6.preferencesController.setSelectedAddress(accounts[0]); }).then(function () { cb(null, _this6.keyringController.fullUpdate()); }).catch(function (reason) { cb(reason); }); } // // Identity Management // }, { key: 'newUnapprovedTransaction', value: function newUnapprovedTransaction(txParams, cb) { log.debug('MetaMaskController newUnapprovedTransaction ' + (0, _stringify2.default)(txParams)); var self = this; self.txController.addUnapprovedTransaction(txParams, function (err, txMeta) { if (err) return cb(err); self.sendUpdate(); self.opts.showUnapprovedTx(txMeta // listen for tx completion (success, fail) );self.txController.once(txMeta.id + ':finished', function (completedTx) { switch (completedTx.status) { case 'submitted': return cb(null, completedTx.hash); case 'rejected': return cb(new Error('MetaMask Tx Signature: User denied transaction signature.')); default: return cb(new Error('MetaMask Tx Signature: Unknown problem: ' + (0, _stringify2.default)(completedTx.txParams))); } }); }); } }, { key: 'newUnsignedMessage', value: function newUnsignedMessage(msgParams, cb) { var msgId = this.messageManager.addUnapprovedMessage(msgParams); this.sendUpdate(); this.opts.showUnconfirmedMessage(); this.messageManager.once(msgId + ':finished', function (data) { switch (data.status) { case 'signed': return cb(null, data.rawSig); case 'rejected': return cb(new Error('MetaMask Message Signature: User denied message signature.')); default: return cb(new Error('MetaMask Message Signature: Unknown problem: ' + (0, _stringify2.default)(msgParams))); } }); } }, { key: 'newUnsignedPersonalMessage', value: function newUnsignedPersonalMessage(msgParams, cb) { if (!msgParams.from) { return cb(new Error('MetaMask Message Signature: from field is required.')); } var msgId = this.personalMessageManager.addUnapprovedMessage(msgParams); this.sendUpdate(); this.opts.showUnconfirmedMessage(); this.personalMessageManager.once(msgId + ':finished', function (data) { switch (data.status) { case 'signed': return cb(null, data.rawSig); case 'rejected': return cb(new Error('MetaMask Message Signature: User denied message signature.')); default: return cb(new Error('MetaMask Message Signature: Unknown problem: ' + (0, _stringify2.default)(msgParams))); } }); } }, { key: 'updateAndApproveTx', value: function updateAndApproveTx(txMeta, cb) { log.debug('MetaMaskController - updateAndApproveTx: ' + (0, _stringify2.default)(txMeta)); var txController = this.txController; txController.updateTx(txMeta); txController.approveTransaction(txMeta.id, cb); } }, { key: 'signMessage', value: function signMessage(msgParams, cb) { var _this7 = this; log.info('MetaMaskController - signMessage'); var msgId = msgParams.metamaskId; // sets the status op the message to 'approved' // and removes the metamaskId for signing return this.messageManager.approveMessage(msgParams).then(function (cleanMsgParams) { // signs the message return _this7.keyringController.signMessage(cleanMsgParams); }).then(function (rawSig) { // tells the listener that the message has been signed // and can be returned to the dapp _this7.messageManager.setMsgStatusSigned(msgId, rawSig); return _this7.getState(); }); } }, { key: 'cancelMessage', value: function cancelMessage(msgId, cb) { var messageManager = this.messageManager; messageManager.rejectMsg(msgId); if (cb && typeof cb === 'function') { cb(null, this.getState()); } } // Prefixed Style Message Signing Methods: }, { key: 'approvePersonalMessage', value: function approvePersonalMessage(msgParams, cb) { var msgId = this.personalMessageManager.addUnapprovedMessage(msgParams); this.sendUpdate(); this.opts.showUnconfirmedMessage(); this.personalMessageManager.once(msgId + ':finished', function (data) { switch (data.status) { case 'signed': return cb(null, data.rawSig); case 'rejected': return cb(new Error('MetaMask Message Signature: User denied transaction signature.')); default: return cb(new Error('MetaMask Message Signature: Unknown problem: ' + (0, _stringify2.default)(msgParams))); } }); } }, { key: 'signPersonalMessage', value: function signPersonalMessage(msgParams) { var _this8 = this; log.info('MetaMaskController - signPersonalMessage'); var msgId = msgParams.metamaskId; // sets the status op the message to 'approved' // and removes the metamaskId for signing return this.personalMessageManager.approveMessage(msgParams).then(function (cleanMsgParams) { // signs the message return _this8.keyringController.signPersonalMessage(cleanMsgParams); }).then(function (rawSig) { // tells the listener that the message has been signed // and can be returned to the dapp _this8.personalMessageManager.setMsgStatusSigned(msgId, rawSig); return _this8.getState(); }); } }, { key: 'cancelPersonalMessage', value: function cancelPersonalMessage(msgId, cb) { var messageManager = this.personalMessageManager; messageManager.rejectMsg(msgId); if (cb && typeof cb === 'function') { cb(null, this.getState()); } } }, { key: 'markAccountsFound', value: function markAccountsFound(cb) { this.configManager.setLostAccounts([]); this.sendUpdate(); cb(null, this.getState()); } }, { key: 'restoreOldVaultAccounts', value: function restoreOldVaultAccounts(migratorOutput) { var serialized = migratorOutput.serialized; return this.keyringController.restoreKeyring(serialized).then(function () { return migratorOutput; }); } }, { key: 'restoreOldLostAccounts', value: function restoreOldLostAccounts(migratorOutput) { var lostAccounts = migratorOutput.lostAccounts; if (lostAccounts) { this.configManager.setLostAccounts(lostAccounts.map(function (acct) { return acct.address; })); return this.importLostAccounts(migratorOutput); } return _promise2.default.resolve(migratorOutput); } // IMPORT LOST ACCOUNTS // @Object with key lostAccounts: @Array accounts <{ address, privateKey }> // Uses the array's private keys to create a new Simple Key Pair keychain // and add it to the keyring controller. }, { key: 'importLostAccounts', value: function importLostAccounts(_ref) { var lostAccounts = _ref.lostAccounts; var privKeys = lostAccounts.map(function (acct) { return acct.privateKey; }); return this.keyringController.restoreKeyring({ type: 'Simple Key Pair', data: privKeys }); } // // config // // Log blocks }, { key: 'setCurrentCurrency', value: function setCurrentCurrency(currencyCode, cb) { try { this.currencyController.setCurrentCurrency(currencyCode); this.currencyController.updateConversionRate(); var data = { conversionRate: this.currencyController.getConversionRate(), currentCurrency: this.currencyController.getCurrentCurrency(), conversionDate: this.currencyController.getConversionDate() }; cb(null, data); } catch (err) { cb(err); } } }, { key: 'buyEth', value: function buyEth(address, amount) { if (!amount) amount = '5'; var network = this.networkController.getNetworkState(); var url = getBuyEthUrl({ network: network, address: address, amount: amount }); if (url) this.platform.openWindow({ url: url }); } }, { key: 'createShapeShiftTx', value: function createShapeShiftTx(depositAddress, depositType) { this.shapeshiftController.createShapeShiftTx(depositAddress, depositType); } // network }, { key: 'setDefaultRpc', value: function setDefaultRpc() { this.networkController.setRpcTarget('http://localhost:8545'); return _promise2.default.resolve('http://localhost:8545'); } }, { key: 'setCustomRpc', value: function setCustomRpc(rpcTarget, rpcList) { this.networkController.setRpcTarget(rpcTarget); return this.preferencesController.updateFrequentRpcList(rpcTarget).then(function () { return _promise2.default.resolve(rpcTarget); }); } }]); return MetamaskController; }(EventEmitter); },{"../manifest.json":1,"./account-import-strategies":2,"./controllers/address-book":5,"./controllers/currency":6,"./controllers/network":7,"./controllers/preferences":8,"./controllers/shapeshift":9,"./controllers/transactions":10,"./keyring-controller":12,"./lib/auto-faucet":13,"./lib/buy-eth-url":14,"./lib/config-manager":15,"./lib/eth-store":16,"./lib/message-manager":17,"./lib/nodeify":19,"./lib/personal-message-manager":22,"./lib/stream-utils.js":25,"./notice-controller":42,"babel-runtime/core-js/json/stringify":78,"babel-runtime/core-js/object/get-prototype-of":84,"babel-runtime/core-js/promise":87,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"babel-runtime/helpers/inherits":93,"babel-runtime/helpers/possibleConstructorReturn":94,"dnode":273,"eth-query":298,"events":314,"obs-store":384,"promise-to-callback":405,"pump":412,"web3-stream-provider/handler":518,"xtend":521}],28:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 2; var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(originalVersionedData) { var versionedData = clone(originalVersionedData); versionedData.meta.version = version; try { if (versionedData.data.config.provider.type === 'etherscan') { versionedData.data.config.provider.type = 'rpc'; versionedData.data.config.provider.rpcTarget = 'https://rpc.metamask.io/'; } } catch (e) {} return _promise2.default.resolve(versionedData); } }; },{"babel-runtime/core-js/promise":87,"clone":145}],29:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 3; var oldTestRpc = 'https://rawtestrpc.metamask.io/'; var newTestRpc = 'https://testrpc.metamask.io/'; var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(originalVersionedData) { var versionedData = clone(originalVersionedData); versionedData.meta.version = version; try { if (versionedData.data.config.provider.rpcTarget === oldTestRpc) { versionedData.data.config.provider.rpcTarget = newTestRpc; } } catch (e) {} return _promise2.default.resolve(versionedData); } }; },{"babel-runtime/core-js/promise":87,"clone":145}],30:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 4; var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(versionedData) { var safeVersionedData = clone(versionedData); safeVersionedData.meta.version = version; try { if (safeVersionedData.data.config.provider.type !== 'rpc') return _promise2.default.resolve(safeVersionedData); switch (safeVersionedData.data.config.provider.rpcTarget) { case 'https://testrpc.metamask.io/': safeVersionedData.data.config.provider = { type: 'testnet' }; break; case 'https://rpc.metamask.io/': safeVersionedData.data.config.provider = { type: 'mainnet' }; break; } } catch (_) {} return _promise2.default.resolve(safeVersionedData); } }; },{"babel-runtime/core-js/promise":87,"clone":145}],31:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 5; /* This migration moves state from the flat state trie into KeyringController substate */ var extend = _dereq_('xtend'); var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(originalVersionedData) { var versionedData = clone(originalVersionedData); versionedData.meta.version = version; try { var state = versionedData.data; var newState = selectSubstateForKeyringController(state); versionedData.data = newState; } catch (err) { console.warn('MetaMask Migration #5' + err.stack); } return _promise2.default.resolve(versionedData); } }; function selectSubstateForKeyringController(state) { var config = state.config; var newState = extend(state, { KeyringController: { vault: state.vault, selectedAccount: config.selectedAccount, walletNicknames: state.walletNicknames } }); delete newState.vault; delete newState.walletNicknames; delete newState.config.selectedAccount; return newState; } },{"babel-runtime/core-js/promise":87,"clone":145,"xtend":521}],32:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 6; /* This migration moves KeyringController.selectedAddress to PreferencesController.selectedAddress */ var extend = _dereq_('xtend'); var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(originalVersionedData) { var versionedData = clone(originalVersionedData); versionedData.meta.version = version; try { var state = versionedData.data; var newState = migrateState(state); versionedData.data = newState; } catch (err) { console.warn('MetaMask Migration #' + version + err.stack); } return _promise2.default.resolve(versionedData); } }; function migrateState(state) { var keyringSubstate = state.KeyringController; // add new state var newState = extend(state, { PreferencesController: { selectedAddress: keyringSubstate.selectedAccount } } // rm old state );delete newState.KeyringController.selectedAccount; return newState; } },{"babel-runtime/core-js/promise":87,"clone":145,"xtend":521}],33:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 7; /* This migration breaks out the TransactionManager substate */ var extend = _dereq_('xtend'); var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(originalVersionedData) { var versionedData = clone(originalVersionedData); versionedData.meta.version = version; try { var state = versionedData.data; var newState = transformState(state); versionedData.data = newState; } catch (err) { console.warn('MetaMask Migration #' + version + err.stack); } return _promise2.default.resolve(versionedData); } }; function transformState(state) { var newState = extend(state, { TransactionManager: { transactions: state.transactions || [], gasMultiplier: state.gasMultiplier || 1 } }); delete newState.transactions; delete newState.gasMultiplier; return newState; } },{"babel-runtime/core-js/promise":87,"clone":145,"xtend":521}],34:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 8; /* This migration breaks out the NoticeController substate */ var extend = _dereq_('xtend'); var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(originalVersionedData) { var versionedData = clone(originalVersionedData); versionedData.meta.version = version; try { var state = versionedData.data; var newState = transformState(state); versionedData.data = newState; } catch (err) { console.warn('MetaMask Migration #' + version + err.stack); } return _promise2.default.resolve(versionedData); } }; function transformState(state) { var newState = extend(state, { NoticeController: { noticesList: state.noticesList || [] } }); delete newState.noticesList; return newState; } },{"babel-runtime/core-js/promise":87,"clone":145,"xtend":521}],35:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 9; /* This migration breaks out the CurrencyController substate */ var merge = _dereq_('deep-extend'); var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(originalVersionedData) { var versionedData = clone(originalVersionedData); versionedData.meta.version = version; try { var state = versionedData.data; var newState = transformState(state); versionedData.data = newState; } catch (err) { console.warn('MetaMask Migration #' + version + err.stack); } return _promise2.default.resolve(versionedData); } }; function transformState(state) { var newState = merge({}, state, { CurrencyController: { currentCurrency: state.currentFiat || state.fiatCurrency || 'USD', conversionRate: state.conversionRate, conversionDate: state.conversionDate } }); delete newState.currentFiat; delete newState.fiatCurrency; delete newState.conversionRate; delete newState.conversionDate; return newState; } },{"babel-runtime/core-js/promise":87,"clone":145,"deep-extend":256}],36:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 10; /* This migration breaks out the ShapeShiftController substate */ var merge = _dereq_('deep-extend'); var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(originalVersionedData) { var versionedData = clone(originalVersionedData); versionedData.meta.version = version; try { var state = versionedData.data; var newState = transformState(state); versionedData.data = newState; } catch (err) { console.warn('MetaMask Migration #' + version + err.stack); } return _promise2.default.resolve(versionedData); } }; function transformState(state) { var newState = merge({}, state, { ShapeShiftController: { shapeShiftTxList: state.shapeShiftTxList || [] } }); delete newState.shapeShiftTxList; return newState; } },{"babel-runtime/core-js/promise":87,"clone":145,"deep-extend":256}],37:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 11; /* This migration removes the discaimer state from our app, which was integrated into our notices. */ var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(originalVersionedData) { var versionedData = clone(originalVersionedData); versionedData.meta.version = version; try { var state = versionedData.data; var newState = transformState(state); versionedData.data = newState; } catch (err) { console.warn('MetaMask Migration #' + version + err.stack); } return _promise2.default.resolve(versionedData); } }; function transformState(state) { var newState = state; delete newState.TOSHash; delete newState.isDisclaimerConfirmed; return newState; } },{"babel-runtime/core-js/promise":87,"clone":145}],38:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 12; /* This migration modifies our notices to delete their body after being read. */ var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(originalVersionedData) { var versionedData = clone(originalVersionedData); versionedData.meta.version = version; try { var state = versionedData.data; var newState = transformState(state); versionedData.data = newState; } catch (err) { console.warn('MetaMask Migration #' + version + err.stack); } return _promise2.default.resolve(versionedData); } }; function transformState(state) { var newState = state; newState.NoticeController.noticesList.forEach(function (notice) { if (notice.read) { notice.body = ''; } }); return newState; } },{"babel-runtime/core-js/promise":87,"clone":145}],39:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 13; /* This migration modifies the network config from ambiguous 'testnet' to explicit 'ropsten' */ var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(originalVersionedData) { var versionedData = clone(originalVersionedData); versionedData.meta.version = version; try { var state = versionedData.data; var newState = transformState(state); versionedData.data = newState; } catch (err) { console.warn('MetaMask Migration #' + version + err.stack); } return _promise2.default.resolve(versionedData); } }; function transformState(state) { var newState = state; if (newState.config.provider.type === 'testnet') { newState.config.provider.type = 'ropsten'; } return newState; } },{"babel-runtime/core-js/promise":87,"clone":145}],40:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var version = 14; /* This migration removes provider from config and moves it too NetworkController. */ var clone = _dereq_('clone'); module.exports = { version: version, migrate: function migrate(originalVersionedData) { var versionedData = clone(originalVersionedData); versionedData.meta.version = version; try { var state = versionedData.data; var newState = transformState(state); versionedData.data = newState; } catch (err) { console.warn('MetaMask Migration #' + version + err.stack); } return _promise2.default.resolve(versionedData); } }; function transformState(state) { var newState = state; newState.NetworkController = {}; newState.NetworkController.provider = newState.config.provider; delete newState.config.provider; return newState; } },{"babel-runtime/core-js/promise":87,"clone":145}],41:[function(_dereq_,module,exports){ 'use strict'; /* The migrator has two methods the user should be concerned with: * * getData(), which returns the app-consumable data object * saveData(), which persists the app-consumable data object. */ // Migrations must start at version 1 or later. // They are objects with a `version` number // and a `migrate` function. // // The `migrate` function receives the previous // config data format, and returns the new one. module.exports = [_dereq_('./002'), _dereq_('./003'), _dereq_('./004'), _dereq_('./005'), _dereq_('./006'), _dereq_('./007'), _dereq_('./008'), _dereq_('./009'), _dereq_('./010'), _dereq_('./011'), _dereq_('./012'), _dereq_('./013'), _dereq_('./014')]; },{"./002":28,"./003":29,"./004":30,"./005":31,"./006":32,"./007":33,"./008":34,"./009":35,"./010":36,"./011":37,"./012":38,"./013":39,"./014":40}],42:[function(_dereq_,module,exports){ 'use strict'; var _promise = _dereq_('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _getPrototypeOf = _dereq_('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = _dereq_('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = _dereq_('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var EventEmitter = _dereq_('events').EventEmitter; var extend = _dereq_('xtend'); var ObservableStore = _dereq_('obs-store'); var hardCodedNotices = _dereq_('../../notices/notices.json'); module.exports = function (_EventEmitter) { (0, _inherits3.default)(NoticeController, _EventEmitter); function NoticeController(opts) { (0, _classCallCheck3.default)(this, NoticeController); var _this = (0, _possibleConstructorReturn3.default)(this, (NoticeController.__proto__ || (0, _getPrototypeOf2.default)(NoticeController)).call(this)); _this.noticePoller = null; var initState = extend({ noticesList: [] }, opts.initState); _this.store = new ObservableStore(initState); _this.memStore = new ObservableStore({}); _this.store.subscribe(function () { return _this._updateMemstore(); }); return _this; } (0, _createClass3.default)(NoticeController, [{ key: 'getNoticesList', value: function getNoticesList() { return this.store.getState().noticesList; } }, { key: 'getUnreadNotices', value: function getUnreadNotices() { var notices = this.getNoticesList(); return notices.filter(function (notice) { return notice.read === false; }); } }, { key: 'getLatestUnreadNotice', value: function getLatestUnreadNotice() { var unreadNotices = this.getUnreadNotices(); return unreadNotices[unreadNotices.length - 1]; } }, { key: 'setNoticesList', value: function setNoticesList(noticesList) { this.store.updateState({ noticesList: noticesList }); return _promise2.default.resolve(true); } }, { key: 'markNoticeRead', value: function markNoticeRead(noticeToMark, cb) { cb = cb || function (err) { if (err) throw err; }; try { var notices = this.getNoticesList(); var index = notices.findIndex(function (currentNotice) { return currentNotice.id === noticeToMark.id; }); notices[index].read = true; notices[index].body = ''; this.setNoticesList(notices); var latestNotice = this.getLatestUnreadNotice(); cb(null, latestNotice); } catch (err) { cb(err); } } }, { key: 'updateNoticesList', value: function updateNoticesList() { var _this2 = this; return this._retrieveNoticeData().then(function (newNotices) { var oldNotices = _this2.getNoticesList(); var combinedNotices = _this2._mergeNotices(oldNotices, newNotices); return _promise2.default.resolve(_this2.setNoticesList(combinedNotices)); }); } }, { key: 'startPolling', value: function startPolling() { var _this3 = this; if (this.noticePoller) { clearInterval(this.noticePoller); } this.noticePoller = setInterval(function () { _this3.noticeController.updateNoticesList(); }, 300000); } }, { key: '_mergeNotices', value: function _mergeNotices(oldNotices, newNotices) { var noticeMap = this._mapNoticeIds(oldNotices); newNotices.forEach(function (notice) { if (noticeMap.indexOf(notice.id) === -1) { oldNotices.push(notice); } }); return oldNotices; } }, { key: '_mapNoticeIds', value: function _mapNoticeIds(notices) { return notices.map(function (notice) { return notice.id; }); } }, { key: '_retrieveNoticeData', value: function _retrieveNoticeData() { // Placeholder for the API. return _promise2.default.resolve(hardCodedNotices); } }, { key: '_updateMemstore', value: function _updateMemstore() { var lastUnreadNotice = this.getLatestUnreadNotice(); var noActiveNotices = !lastUnreadNotice; this.memStore.updateState({ lastUnreadNotice: lastUnreadNotice, noActiveNotices: noActiveNotices }); } }]); return NoticeController; }(EventEmitter); },{"../../notices/notices.json":522,"babel-runtime/core-js/object/get-prototype-of":84,"babel-runtime/core-js/promise":87,"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"babel-runtime/helpers/inherits":93,"babel-runtime/helpers/possibleConstructorReturn":94,"events":314,"obs-store":384,"xtend":521}],43:[function(_dereq_,module,exports){ 'use strict'; var _classCallCheck2 = _dereq_('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = _dereq_('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var extension = _dereq_('extensionizer'); var ExtensionPlatform = function () { function ExtensionPlatform() { (0, _classCallCheck3.default)(this, ExtensionPlatform); } (0, _createClass3.default)(ExtensionPlatform, [{ key: 'reload', // // Public // value: function reload() { extension.runtime.reload(); } }, { key: 'openWindow', value: function openWindow(_ref) { var url = _ref.url; extension.tabs.create({ url: url }); } }, { key: 'getVersion', value: function getVersion() { return extension.runtime.getManifest().version; } }]); return ExtensionPlatform; }(); module.exports = ExtensionPlatform; },{"babel-runtime/helpers/classCallCheck":91,"babel-runtime/helpers/createClass":92,"extensionizer":317}],44:[function(_dereq_,module,exports){ (function (Buffer){ "use strict"; (function() { var root = this; var previous_mymodule = root.mymodule; var createBuffer = null, convertBytesToString, convertStringToBytes = null; var slowCreateBuffer = function(arg) { // Passed in a single number, the length to pre-allocate if (typeof arg === 'number') { var result = []; for (var i = 0; i < arg; i++) { result.push(0); } return result; } else { // Make sure they are passing sensible data for (var i = 0; i < arg.length; i++) { if (arg[i] < 0 || arg[i] >= 256 || typeof arg[i] !== 'number') { throw new Error('invalid byte at index ' + i + '(' + arg[i] + ')'); } } // Most array-like things should support this if (arg.slice) { return arg.slice(0); } // Something *weird*; copy it into an array (see PR#2) var result = []; for (var i = 0; i < arg.length; i++) { result.push(arg[i]); } return result; } } if (typeof(Buffer) === 'undefined') { createBuffer = slowCreateBuffer; Array.prototype.copy = function(targetArray, targetStart, sourceStart, sourceEnd) { if (targetStart == null) { targetStart = 0; } if (sourceStart == null) { sourceStart = 0; } if (sourceEnd == null) { sourceEnd = this.length; } for (var i = sourceStart; i < sourceEnd; i++) { targetArray[targetStart++] = this[i]; } } convertStringToBytes = function(text, encoding) { // "utf8", "utf-8", "utf 8", etc if (encoding == null || encoding.toLowerCase().replace(/ |-/g, "") == 'utf8') { var result = [], i = 0; text = encodeURI(text); while (i < text.length) { var c = text.charCodeAt(i++); // if it is a % sign, encode the following 2 bytes as a hex value if (c === 37) { result.push(parseInt(text.substr(i, 2), 16)) i += 2; // otherwise, just the actual byte } else { result.push(c) } } return result; // "hex" } else if (encoding.toLowerCase() == 'hex') { var result = []; for (var i = 0; i < text.length; i += 2) { result.push(parseInt(text.substr(i, 2), 16)); } return result; } // @TODO: Base64... return null; } // http://ixti.net/development/javascript/2011/11/11/base64-encodedecode-of-utf8-in-browser-with-js.html var Hex = '0123456789abcdef'; convertBytesToString = function(bytes, encoding) { // "utf8", "utf-8", "utf 8", etc if (encoding == null || encoding.toLowerCase().replace(/ |-/g, "") == 'utf8') { var result = [], i = 0; while (i < bytes.length) { var c = bytes[i]; if (c < 128) { result.push(String.fromCharCode(c)); i++; } else if (c > 191 && c < 224) { result.push(String.fromCharCode(((c & 0x1f) << 6) | (bytes[i + 1] & 0x3f))); i += 2; } else { result.push(String.fromCharCode(((c & 0x0f) << 12) | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f))); i += 3; } } return result.join(''); // "hex" } else if (encoding.toLowerCase() == 'hex') { var result = []; for (var i = 0; i < bytes.length; i++) { var v = bytes[i]; result.push(Hex[(v & 0xf0) >> 4] + Hex[v & 0x0f]); } return result.join(''); } return result } } else { createBuffer = function(arg) { return new Buffer(arg); } convertStringToBytes = function(text, encoding) { return new Buffer(text, encoding); } convertBytesToString = function(bytes, encoding) { return (new Buffer(bytes)).toString(encoding); } } // Number of rounds by keysize var numberOfRounds = {16: 10, 24: 12, 32: 14} // Round constant words var rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91]; // S-box and Inverse S-box (S is for Substitution) var S = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]; var Si =[0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]; // Transformations for encryption var T1 = [0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a]; var T2 = [0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616]; var T3 = [0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16]; var T4 = [0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c]; // Transformations for decryption var T5 = [0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742]; var T6 = [0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857]; var T7 = [0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8]; var T8 = [0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0]; // Transformations for decryption key expansion var U1 = [0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]; var U2 = [0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697]; var U3 = [0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46]; var U4 = [0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d]; function convertToInt32(bytes) { var result = []; for (var i = 0; i < bytes.length; i += 4) { result.push( (bytes[i ] << 24) | (bytes[i + 1] << 16) | (bytes[i + 2] << 8) | bytes[i + 3] ); } return result; } var AES = function(key) { this.key = createBuffer(key); this._prepare(); } AES.prototype._prepare = function() { var rounds = numberOfRounds[this.key.length]; if (rounds == null) { throw new Error('invalid key size (must be length 16, 24 or 32)'); } // encryption round keys this._Ke = []; // decryption round keys this._Kd = []; for (var i = 0; i <= rounds; i++) { this._Ke.push([0, 0, 0, 0]); this._Kd.push([0, 0, 0, 0]); } var roundKeyCount = (rounds + 1) * 4; var KC = this.key.length / 4; // convert the key into ints var tk = convertToInt32(this.key); // copy values into round key arrays var index; for (var i = 0; i < KC; i++) { index = i >> 2; this._Ke[index][i % 4] = tk[i]; this._Kd[rounds - index][i % 4] = tk[i]; } // key expansion (fips-197 section 5.2) var rconpointer = 0; var t = KC, tt; while (t < roundKeyCount) { tt = tk[KC - 1]; tk[0] ^= ((S[(tt >> 16) & 0xFF] << 24) ^ (S[(tt >> 8) & 0xFF] << 16) ^ (S[ tt & 0xFF] << 8) ^ S[(tt >> 24) & 0xFF] ^ (rcon[rconpointer] << 24)); rconpointer += 1; // key expansion (for non-256 bit) if (KC != 8) { for (var i = 1; i < KC; i++) { tk[i] ^= tk[i - 1]; } // key expansion for 256-bit keys is "slightly different" (fips-197) } else { for (var i = 1; i < (KC / 2); i++) { tk[i] ^= tk[i - 1]; } tt = tk[(KC / 2) - 1]; tk[KC / 2] ^= (S[ tt & 0xFF] ^ (S[(tt >> 8) & 0xFF] << 8) ^ (S[(tt >> 16) & 0xFF] << 16) ^ (S[(tt >> 24) & 0xFF] << 24)); for (var i = (KC / 2) + 1; i < KC; i++) { tk[i] ^= tk[i - 1]; } } // copy values into round key arrays var i = 0, r, c; while (i < KC && t < roundKeyCount) { r = t >> 2; c = t % 4; this._Ke[r][c] = tk[i]; this._Kd[rounds - r][c] = tk[i++]; t++; } } // inverse-cipher-ify the decryption round key (fips-197 section 5.3) for (var r = 1; r < rounds; r++) { for (var c = 0; c < 4; c++) { tt = this._Kd[r][c]; this._Kd[r][c] = (U1[(tt >> 24) & 0xFF] ^ U2[(tt >> 16) & 0xFF] ^ U3[(tt >> 8) & 0xFF] ^ U4[ tt & 0xFF]); } } } AES.prototype.encrypt = function(plaintext) { if (plaintext.length != 16) { return new Error('plaintext must be a block of size 16'); } var rounds = this._Ke.length - 1; var a = [0, 0, 0, 0]; // convert plaintext to (ints ^ key) var t = convertToInt32(plaintext); for (var i = 0; i < 4; i++) { t[i] ^= this._Ke[0][i]; } // apply round transforms for (var r = 1; r < rounds; r++) { for (var i = 0; i < 4; i++) { a[i] = (T1[(t[ i ] >> 24) & 0xff] ^ T2[(t[(i + 1) % 4] >> 16) & 0xff] ^ T3[(t[(i + 2) % 4] >> 8) & 0xff] ^ T4[ t[(i + 3) % 4] & 0xff] ^ this._Ke[r][i]); } t = a.slice(0); } // the last round is special var result = createBuffer(16), tt; for (var i = 0; i < 4; i++) { tt = this._Ke[rounds][i]; result[4 * i ] = (S[(t[ i ] >> 24) & 0xff] ^ (tt >> 24)) & 0xff; result[4 * i + 1] = (S[(t[(i + 1) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff; result[4 * i + 2] = (S[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff; result[4 * i + 3] = (S[ t[(i + 3) % 4] & 0xff] ^ tt ) & 0xff; } return result; } AES.prototype.decrypt = function(ciphertext) { if (ciphertext.length != 16) { return new Error('ciphertext must be a block of size 16'); } var rounds = this._Kd.length - 1; var a = [0, 0, 0, 0]; // convert plaintext to (ints ^ key) var t = convertToInt32(ciphertext); for (var i = 0; i < 4; i++) { t[i] ^= this._Kd[0][i]; } // apply round transforms for (var r = 1; r < rounds; r++) { for (var i = 0; i < 4; i++) { a[i] = (T5[(t[ i ] >> 24) & 0xff] ^ T6[(t[(i + 3) % 4] >> 16) & 0xff] ^ T7[(t[(i + 2) % 4] >> 8) & 0xff] ^ T8[ t[(i + 1) % 4] & 0xff] ^ this._Kd[r][i]); } t = a.slice(0); } // the last round is special var result = createBuffer(16), tt; for (var i = 0; i < 4; i++) { tt = this._Kd[rounds][i]; result[4 * i ] = (Si[(t[ i ] >> 24) & 0xff] ^ (tt >> 24)) & 0xff; result[4 * i + 1] = (Si[(t[(i + 3) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff; result[4 * i + 2] = (Si[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff; result[4 * i + 3] = (Si[ t[(i + 1) % 4] & 0xff] ^ tt ) & 0xff; } return result; } /** * Mode Of Operation - Electonic Codebook (ECB) */ var ModeOfOperationECB = function(key) { this.description = "Electronic Code Block"; this.name = "ecb"; this._aes = new AES(key); } ModeOfOperationECB.prototype.encrypt = function(plaintext) { return this._aes.encrypt(plaintext); } ModeOfOperationECB.prototype.decrypt = function(ciphertext, encoding) { return this._aes.decrypt(ciphertext); } /** * Mode Of Operation - Cipher Block Chaining (CBC) */ var ModeOfOperationCBC = function(key, iv) { this.description = "Cipher Block Chaining"; this.name = "cbc"; if (iv === null) { iv = createBuffer([0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); } else if (iv.length != 16) { return new Error('initialation vector iv must be of length 16'); } this._lastCipherblock = createBuffer(iv); this._aes = new AES(key); } ModeOfOperationCBC.prototype.encrypt = function(plaintext) { if (plaintext.length != 16) { return new Error('plaintext must be a block of size 16'); } var precipherblock = createBuffer(plaintext); for (var i = 0; i < 16; i++) { precipherblock[i] ^= this._lastCipherblock[i]; } this._lastCipherblock = this._aes.encrypt(precipherblock); return this._lastCipherblock; } ModeOfOperationCBC.prototype.decrypt = function(ciphertext) { if (ciphertext.length != 16) { return new Error('ciphertext must be a block of size 16'); } var plaintext = this._aes.decrypt(ciphertext); for (var i = 0; i < 16; i++) { plaintext[i] ^= this._lastCipherblock[i]; } ciphertext.copy(this._lastCipherblock); return plaintext; } /** * Mode Of Operation - Cipher Feedback (CFB) */ var ModeOfOperationCFB = function(key, iv, segmentSize) { this.description = "Cipher Feedback"; this.name = "cfb"; if (iv === null) { iv = createBuffer([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); } else if (iv.length != 16) { return new Error('initialation vector iv must be of length 16'); } if (!segmentSize) { segmentSize = 1; } this.segmentSize = segmentSize; this._shiftRegister = createBuffer(iv); this._aes = new AES(key); } ModeOfOperationCFB.prototype.encrypt = function(plaintext) { if ((plaintext.length % this.segmentSize) != 0) { return new Error('plaintext must be a block of size module segmentSize (' + this.segmentSize + ')'); } var encrypted = createBuffer(plaintext); var xorSegment; for (var i = 0; i < encrypted.length; i += this.segmentSize) { xorSegment = this._aes.encrypt(this._shiftRegister); for (var j = 0; j < this.segmentSize; j++) { encrypted[i + j] ^= xorSegment[j]; } // Shift the register this._shiftRegister.copy(this._shiftRegister, 0, this.segmentSize); encrypted.copy(this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize); } return encrypted; } ModeOfOperationCFB.prototype.decrypt = function(ciphertext) { if ((ciphertext.length % this.segmentSize) != 0) { return new Error('ciphertext must be a block of size module segmentSize (' + this.segmentSize + ')'); } var plaintext = createBuffer(ciphertext); var xorSegment; for (var i = 0; i < plaintext.length; i += this.segmentSize) { xorSegment = this._aes.encrypt(this._shiftRegister); for (var j = 0; j < this.segmentSize; j++) { plaintext[i + j] ^= xorSegment[j]; } // Shift the register this._shiftRegister.copy(this._shiftRegister, 0, this.segmentSize); ciphertext.copy(this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize); } return plaintext; } /** * Mode Of Operation - Output Feedback (OFB) */ var ModeOfOperationOFB = function(key, iv) { this.description = "Output Feedback"; this.name = "ofb"; if (iv === null) { iv = createBuffer([0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); } else if (iv.length != 16) { return new Error('initialation vector iv must be of length 16'); } this._lastPrecipher = createBuffer(iv); this._lastPrecipherIndex = 16; this._aes = new AES(key); } ModeOfOperationOFB.prototype.encrypt = function(plaintext) { var encrypted = createBuffer(plaintext); for (var i = 0; i < encrypted.length; i++) { if (this._lastPrecipherIndex === 16) { this._lastPrecipher = this._aes.encrypt(this._lastPrecipher); this._lastPrecipherIndex = 0; } encrypted[i] ^= this._lastPrecipher[this._lastPrecipherIndex++]; } return encrypted; } // Decryption is symetric ModeOfOperationOFB.prototype.decrypt = ModeOfOperationOFB.prototype.encrypt; /** * Counter object for CTR common mode of operation */ var Counter = function(initialValue) { if (initialValue === null || initialValue === undefined) { initialValue = 1; } if (typeof(initialValue) === 'number') { this._counter = createBuffer([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); this.setValue(initialValue); } else { this.setBytes(initialValue); } } Counter.prototype.setValue = function(value) { if (typeof(value) !== 'number') { throw new Error('value must be a number'); } for (var index = 15; index >= 0; --index) { this._counter[index] = value % 256; value = value >> 8; } } Counter.prototype.setBytes = function(bytes) { if (bytes.length != 16) { throw new Error('invalid counter bytes size (must be 16)'); } this._counter = createBuffer(bytes); }; Counter.prototype.increment = function() { for (var i = 15; i >= 0; i--) { if (this._counter[i] === 255) { this._counter[i] = 0; } else { this._counter[i]++; break; } } } /** * Mode Of Operation - Counter (CTR) */ var ModeOfOperationCTR = function(key, counter) { this.description = "Counter"; this.name = "ctr"; if (counter === null) { counter = new Counter() } this._counter = counter; this._remainingCounter = null; this._remainingCounterIndex = 16; this._aes = new AES(key); } ModeOfOperationCTR.prototype.encrypt = function(plaintext) { var encrypted = createBuffer(plaintext); for (var i = 0; i < encrypted.length; i++) { if (this._remainingCounterIndex === 16) { this._remainingCounter = this._aes.encrypt(this._counter._counter); this._remainingCounterIndex = 0; this._counter.increment(); } encrypted[i] ^= this._remainingCounter[this._remainingCounterIndex++]; } return encrypted; } // Decryption is symetric ModeOfOperationCTR.prototype.decrypt = ModeOfOperationCTR.prototype.encrypt; // The bsic modes of operation as a map var ModeOfOperation = { ecb: ModeOfOperationECB, cbc: ModeOfOperationCBC, cfb: ModeOfOperationCFB, ofb: ModeOfOperationOFB, ctr: ModeOfOperationCTR }; /////////////////////// // Exports // The block cipher var aesjs = { AES: AES, Counter: Counter, ModeOfOperation: ModeOfOperation, util: { convertBytesToString: convertBytesToString, convertStringToBytes: convertStringToBytes, _slowCreateBuffer: slowCreateBuffer } }; if(typeof exports !== 'undefined') { exports.AES = AES; exports.Counter = Counter; exports.ModeOfOperation = ModeOfOperation; exports.util = { convertBytesToString: convertBytesToString, convertStringToBytes: convertStringToBytes, _slowCreateBuffer: slowCreateBuffer } /* if(typeof module !== 'undefined' && module.exports) { exports = module.exports = export; } exports.mymodule = mymodule; */ } else { root.aesjs = aesjs; } }).call(this); }).call(this,_dereq_("buffer").Buffer) },{"buffer":142}],45:[function(_dereq_,module,exports){ var asn1 = exports; asn1.bignum = _dereq_('bn.js'); asn1.define = _dereq_('./asn1/api').define; asn1.base = _dereq_('./asn1/base'); asn1.constants = _dereq_('./asn1/constants'); asn1.decoders = _dereq_('./asn1/decoders'); asn1.encoders = _dereq_('./asn1/encoders'); },{"./asn1/api":46,"./asn1/base":48,"./asn1/constants":52,"./asn1/decoders":54,"./asn1/encoders":57,"bn.js":106}],46:[function(_dereq_,module,exports){ var asn1 = _dereq_('../asn1'); var inherits = _dereq_('inherits'); var api = exports; api.define = function define(name, body) { return new Entity(name, body); }; function Entity(name, body) { this.name = name; this.body = body; this.decoders = {}; this.encoders = {}; }; Entity.prototype._createNamed = function createNamed(base) { var named; try { named = _dereq_('vm').runInThisContext( '(function ' + this.name + '(entity) {\n' + ' this._initNamed(entity);\n' + '})' ); } catch (e) { named = function (entity) { this._initNamed(entity); }; } inherits(named, base); named.prototype._initNamed = function initnamed(entity) { base.call(this, entity); }; return new named(this); }; Entity.prototype._getDecoder = function _getDecoder(enc) { enc = enc || 'der'; // Lazily create decoder if (!this.decoders.hasOwnProperty(enc)) this.decoders[enc] = this._createNamed(asn1.decoders[enc]); return this.decoders[enc]; }; Entity.prototype.decode = function decode(data, enc, options) { return this._getDecoder(enc).decode(data, options); }; Entity.prototype._getEncoder = function _getEncoder(enc) { enc = enc || 'der'; // Lazily create encoder if (!this.encoders.hasOwnProperty(enc)) this.encoders[enc] = this._createNamed(asn1.encoders[enc]); return this.encoders[enc]; }; Entity.prototype.encode = function encode(data, enc, /* internal */ reporter) { return this._getEncoder(enc).encode(data, reporter); }; },{"../asn1":45,"inherits":332,"vm":471}],47:[function(_dereq_,module,exports){ var inherits = _dereq_('inherits'); var Reporter = _dereq_('../base').Reporter; var Buffer = _dereq_('buffer').Buffer; function DecoderBuffer(base, options) { Reporter.call(this, options); if (!Buffer.isBuffer(base)) { this.error('Input not Buffer'); return; } this.base = base; this.offset = 0; this.length = base.length; } inherits(DecoderBuffer, Reporter); exports.DecoderBuffer = DecoderBuffer; DecoderBuffer.prototype.save = function save() { return { offset: this.offset, reporter: Reporter.prototype.save.call(this) }; }; DecoderBuffer.prototype.restore = function restore(save) { // Return skipped data var res = new DecoderBuffer(this.base); res.offset = save.offset; res.length = this.offset; this.offset = save.offset; Reporter.prototype.restore.call(this, save.reporter); return res; }; DecoderBuffer.prototype.isEmpty = function isEmpty() { return this.offset === this.length; }; DecoderBuffer.prototype.readUInt8 = function readUInt8(fail) { if (this.offset + 1 <= this.length) return this.base.readUInt8(this.offset++, true); else return this.error(fail || 'DecoderBuffer overrun'); } DecoderBuffer.prototype.skip = function skip(bytes, fail) { if (!(this.offset + bytes <= this.length)) return this.error(fail || 'DecoderBuffer overrun'); var res = new DecoderBuffer(this.base); // Share reporter state res._reporterState = this._reporterState; res.offset = this.offset; res.length = this.offset + bytes; this.offset += bytes; return res; } DecoderBuffer.prototype.raw = function raw(save) { return this.base.slice(save ? save.offset : this.offset, this.length); } function EncoderBuffer(value, reporter) { if (Array.isArray(value)) { this.length = 0; this.value = value.map(function(item) { if (!(item instanceof EncoderBuffer)) item = new EncoderBuffer(item, reporter); this.length += item.length; return item; }, this); } else if (typeof value === 'number') { if (!(0 <= value && value <= 0xff)) return reporter.error('non-byte EncoderBuffer value'); this.value = value; this.length = 1; } else if (typeof value === 'string') { this.value = value; this.length = Buffer.byteLength(value); } else if (Buffer.isBuffer(value)) { this.value = value; this.length = value.length; } else { return reporter.error('Unsupported type: ' + typeof value); } } exports.EncoderBuffer = EncoderBuffer; EncoderBuffer.prototype.join = function join(out, offset) { if (!out) out = new Buffer(this.length); if (!offset) offset = 0; if (this.length === 0) return out; if (Array.isArray(this.value)) { this.value.forEach(function(item) { item.join(out, offset); offset += item.length; }); } else { if (typeof this.value === 'number') out[offset] = this.value; else if (typeof this.value === 'string') out.write(this.value, offset); else if (Buffer.isBuffer(this.value)) this.value.copy(out, offset); offset += this.length; } return out; }; },{"../base":48,"buffer":142,"inherits":332}],48:[function(_dereq_,module,exports){ var base = exports; base.Reporter = _dereq_('./reporter').Reporter; base.DecoderBuffer = _dereq_('./buffer').DecoderBuffer; base.EncoderBuffer = _dereq_('./buffer').EncoderBuffer; base.Node = _dereq_('./node'); },{"./buffer":47,"./node":49,"./reporter":50}],49:[function(_dereq_,module,exports){ var Reporter = _dereq_('../base').Reporter; var EncoderBuffer = _dereq_('../base').EncoderBuffer; var DecoderBuffer = _dereq_('../base').DecoderBuffer; var assert = _dereq_('minimalistic-assert'); // Supported tags var tags = [ 'seq', 'seqof', 'set', 'setof', 'objid', 'bool', 'gentime', 'utctime', 'null_', 'enum', 'int', 'objDesc', 'bitstr', 'bmpstr', 'charstr', 'genstr', 'graphstr', 'ia5str', 'iso646str', 'numstr', 'octstr', 'printstr', 't61str', 'unistr', 'utf8str', 'videostr' ]; // Public methods list var methods = [ 'key', 'obj', 'use', 'optional', 'explicit', 'implicit', 'def', 'choice', 'any', 'contains' ].concat(tags); // Overrided methods list var overrided = [ '_peekTag', '_decodeTag', '_use', '_decodeStr', '_decodeObjid', '_decodeTime', '_decodeNull', '_decodeInt', '_decodeBool', '_decodeList', '_encodeComposite', '_encodeStr', '_encodeObjid', '_encodeTime', '_encodeNull', '_encodeInt', '_encodeBool' ]; function Node(enc, parent) { var state = {}; this._baseState = state; state.enc = enc; state.parent = parent || null; state.children = null; // State state.tag = null; state.args = null; state.reverseArgs = null; state.choice = null; state.optional = false; state.any = false; state.obj = false; state.use = null; state.useDecoder = null; state.key = null; state['default'] = null; state.explicit = null; state.implicit = null; state.contains = null; // Should create new instance on each method if (!state.parent) { state.children = []; this._wrap(); } } module.exports = Node; var stateProps = [ 'enc', 'parent', 'children', 'tag', 'args', 'reverseArgs', 'choice', 'optional', 'any', 'obj', 'use', 'alteredUse', 'key', 'default', 'explicit', 'implicit', 'contains' ]; Node.prototype.clone = function clone() { var state = this._baseState; var cstate = {}; stateProps.forEach(function(prop) { cstate[prop] = state[prop]; }); var res = new this.constructor(cstate.parent); res._baseState = cstate; return res; }; Node.prototype._wrap = function wrap() { var state = this._baseState; methods.forEach(function(method) { this[method] = function _wrappedMethod() { var clone = new this.constructor(this); state.children.push(clone); return clone[method].apply(clone, arguments); }; }, this); }; Node.prototype._init = function init(body) { var state = this._baseState; assert(state.parent === null); body.call(this); // Filter children state.children = state.children.filter(function(child) { return child._baseState.parent === this; }, this); assert.equal(state.children.length, 1, 'Root node can have only one child'); }; Node.prototype._useArgs = function useArgs(args) { var state = this._baseState; // Filter children and args var children = args.filter(function(arg) { return arg instanceof this.constructor; }, this); args = args.filter(function(arg) { return !(arg instanceof this.constructor); }, this); if (children.length !== 0) { assert(state.children === null); state.children = children; // Replace parent to maintain backward link children.forEach(function(child) { child._baseState.parent = this; }, this); } if (args.length !== 0) { assert(state.args === null); state.args = args; state.reverseArgs = args.map(function(arg) { if (typeof arg !== 'object' || arg.constructor !== Object) return arg; var res = {}; Object.keys(arg).forEach(function(key) { if (key == (key | 0)) key |= 0; var value = arg[key]; res[value] = key; }); return res; }); } }; // // Overrided methods // overrided.forEach(function(method) { Node.prototype[method] = function _overrided() { var state = this._baseState; throw new Error(method + ' not implemented for encoding: ' + state.enc); }; }); // // Public methods // tags.forEach(function(tag) { Node.prototype[tag] = function _tagMethod() { var state = this._baseState; var args = Array.prototype.slice.call(arguments); assert(state.tag === null); state.tag = tag; this._useArgs(args); return this; }; }); Node.prototype.use = function use(item) { assert(item); var state = this._baseState; assert(state.use === null); state.use = item; return this; }; Node.prototype.optional = function optional() { var state = this._baseState; state.optional = true; return this; }; Node.prototype.def = function def(val) { var state = this._baseState; assert(state['default'] === null); state['default'] = val; state.optional = true; return this; }; Node.prototype.explicit = function explicit(num) { var state = this._baseState; assert(state.explicit === null && state.implicit === null); state.explicit = num; return this; }; Node.prototype.implicit = function implicit(num) { var state = this._baseState; assert(state.explicit === null && state.implicit === null); state.implicit = num; return this; }; Node.prototype.obj = function obj() { var state = this._baseState; var args = Array.prototype.slice.call(arguments); state.obj = true; if (args.length !== 0) this._useArgs(args); return this; }; Node.prototype.key = function key(newKey) { var state = this._baseState; assert(state.key === null); state.key = newKey; return this; }; Node.prototype.any = function any() { var state = this._baseState; state.any = true; return this; }; Node.prototype.choice = function choice(obj) { var state = this._baseState; assert(state.choice === null); state.choice = obj; this._useArgs(Object.keys(obj).map(function(key) { return obj[key]; })); return this; }; Node.prototype.contains = function contains(item) { var state = this._baseState; assert(state.use === null); state.contains = item; return this; }; // // Decoding // Node.prototype._decode = function decode(input, options) { var state = this._baseState; // Decode root node if (state.parent === null) return input.wrapResult(state.children[0]._decode(input, options)); var result = state['default']; var present = true; var prevKey = null; if (state.key !== null) prevKey = input.enterKey(state.key); // Check if tag is there if (state.optional) { var tag = null; if (state.explicit !== null) tag = state.explicit; else if (state.implicit !== null) tag = state.implicit; else if (state.tag !== null) tag = state.tag; if (tag === null && !state.any) { // Trial and Error var save = input.save(); try { if (state.choice === null) this._decodeGeneric(state.tag, input, options); else this._decodeChoice(input, options); present = true; } catch (e) { present = false; } input.restore(save); } else { present = this._peekTag(input, tag, state.any); if (input.isError(present)) return present; } } // Push object on stack var prevObj; if (state.obj && present) prevObj = input.enterObject(); if (present) { // Unwrap explicit values if (state.explicit !== null) { var explicit = this._decodeTag(input, state.explicit); if (input.isError(explicit)) return explicit; input = explicit; } var start = input.offset; // Unwrap implicit and normal values if (state.use === null && state.choice === null) { if (state.any) var save = input.save(); var body = this._decodeTag( input, state.implicit !== null ? state.implicit : state.tag, state.any ); if (input.isError(body)) return body; if (state.any) result = input.raw(save); else input = body; } if (options && options.track && state.tag !== null) options.track(input.path(), start, input.length, 'tagged'); if (options && options.track && state.tag !== null) options.track(input.path(), input.offset, input.length, 'content'); // Select proper method for tag if (state.any) result = result; else if (state.choice === null) result = this._decodeGeneric(state.tag, input, options); else result = this._decodeChoice(input, options); if (input.isError(result)) return result; // Decode children if (!state.any && state.choice === null && state.children !== null) { state.children.forEach(function decodeChildren(child) { // NOTE: We are ignoring errors here, to let parser continue with other // parts of encoded data child._decode(input, options); }); } // Decode contained/encoded by schema, only in bit or octet strings if (state.contains && (state.tag === 'octstr' || state.tag === 'bitstr')) { var data = new DecoderBuffer(result); result = this._getUse(state.contains, input._reporterState.obj) ._decode(data, options); } } // Pop object if (state.obj && present) result = input.leaveObject(prevObj); // Set key if (state.key !== null && (result !== null || present === true)) input.leaveKey(prevKey, state.key, result); else if (prevKey !== null) input.exitKey(prevKey); return result; }; Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) { var state = this._baseState; if (tag === 'seq' || tag === 'set') return null; if (tag === 'seqof' || tag === 'setof') return this._decodeList(input, tag, state.args[0], options); else if (/str$/.test(tag)) return this._decodeStr(input, tag, options); else if (tag === 'objid' && state.args) return this._decodeObjid(input, state.args[0], state.args[1], options); else if (tag === 'objid') return this._decodeObjid(input, null, null, options); else if (tag === 'gentime' || tag === 'utctime') return this._decodeTime(input, tag, options); else if (tag === 'null_') return this._decodeNull(input, options); else if (tag === 'bool') return this._decodeBool(input, options); else if (tag === 'objDesc') return this._decodeStr(input, tag, options); else if (tag === 'int' || tag === 'enum') return this._decodeInt(input, state.args && state.args[0], options); if (state.use !== null) { return this._getUse(state.use, input._reporterState.obj) ._decode(input, options); } else { return input.error('unknown tag: ' + tag); } }; Node.prototype._getUse = function _getUse(entity, obj) { var state = this._baseState; // Create altered use decoder if implicit is set state.useDecoder = this._use(entity, obj); assert(state.useDecoder._baseState.parent === null); state.useDecoder = state.useDecoder._baseState.children[0]; if (state.implicit !== state.useDecoder._baseState.implicit) { state.useDecoder = state.useDecoder.clone(); state.useDecoder._baseState.implicit = state.implicit; } return state.useDecoder; }; Node.prototype._decodeChoice = function decodeChoice(input, options) { var state = this._baseState; var result = null; var match = false; Object.keys(state.choice).some(function(key) { var save = input.save(); var node = state.choice[key]; try { var value = node._decode(input, options); if (input.isError(value)) return false; result = { type: key, value: value }; match = true; } catch (e) { input.restore(save); return false; } return true; }, this); if (!match) return input.error('Choice not matched'); return result; }; // // Encoding // Node.prototype._createEncoderBuffer = function createEncoderBuffer(data) { return new EncoderBuffer(data, this.reporter); }; Node.prototype._encode = function encode(data, reporter, parent) { var state = this._baseState; if (state['default'] !== null && state['default'] === data) return; var result = this._encodeValue(data, reporter, parent); if (result === undefined) return; if (this._skipDefault(result, reporter, parent)) return; return result; }; Node.prototype._encodeValue = function encode(data, reporter, parent) { var state = this._baseState; // Decode root node if (state.parent === null) return state.children[0]._encode(data, reporter || new Reporter()); var result = null; // Set reporter to share it with a child class this.reporter = reporter; // Check if data is there if (state.optional && data === undefined) { if (state['default'] !== null) data = state['default'] else return; } // Encode children first var content = null; var primitive = false; if (state.any) { // Anything that was given is translated to buffer result = this._createEncoderBuffer(data); } else if (state.choice) { result = this._encodeChoice(data, reporter); } else if (state.contains) { content = this._getUse(state.contains, parent)._encode(data, reporter); primitive = true; } else if (state.children) { content = state.children.map(function(child) { if (child._baseState.tag === 'null_') return child._encode(null, reporter, data); if (child._baseState.key === null) return reporter.error('Child should have a key'); var prevKey = reporter.enterKey(child._baseState.key); if (typeof data !== 'object') return reporter.error('Child expected, but input is not object'); var res = child._encode(data[child._baseState.key], reporter, data); reporter.leaveKey(prevKey); return res; }, this).filter(function(child) { return child; }); content = this._createEncoderBuffer(content); } else { if (state.tag === 'seqof' || state.tag === 'setof') { // TODO(indutny): this should be thrown on DSL level if (!(state.args && state.args.length === 1)) return reporter.error('Too many args for : ' + state.tag); if (!Array.isArray(data)) return reporter.error('seqof/setof, but data is not Array'); var child = this.clone(); child._baseState.implicit = null; content = this._createEncoderBuffer(data.map(function(item) { var state = this._baseState; return this._getUse(state.args[0], data)._encode(item, reporter); }, child)); } else if (state.use !== null) { result = this._getUse(state.use, parent)._encode(data, reporter); } else { content = this._encodePrimitive(state.tag, data); primitive = true; } } // Encode data itself var result; if (!state.any && state.choice === null) { var tag = state.implicit !== null ? state.implicit : state.tag; var cls = state.implicit === null ? 'universal' : 'context'; if (tag === null) { if (state.use === null) reporter.error('Tag could be ommited only for .use()'); } else { if (state.use === null) result = this._encodeComposite(tag, primitive, cls, content); } } // Wrap in explicit if (state.explicit !== null) result = this._encodeComposite(state.explicit, false, 'context', result); return result; }; Node.prototype._encodeChoice = function encodeChoice(data, reporter) { var state = this._baseState; var node = state.choice[data.type]; if (!node) { assert( false, data.type + ' not found in ' + JSON.stringify(Object.keys(state.choice))); } return node._encode(data.value, reporter); }; Node.prototype._encodePrimitive = function encodePrimitive(tag, data) { var state = this._baseState; if (/str$/.test(tag)) return this._encodeStr(data, tag); else if (tag === 'objid' && state.args) return this._encodeObjid(data, state.reverseArgs[0], state.args[1]); else if (tag === 'objid') return this._encodeObjid(data, null, null); else if (tag === 'gentime' || tag === 'utctime') return this._encodeTime(data, tag); else if (tag === 'null_') return this._encodeNull(); else if (tag === 'int' || tag === 'enum') return this._encodeInt(data, state.args && state.reverseArgs[0]); else if (tag === 'bool') return this._encodeBool(data); else if (tag === 'objDesc') return this._encodeStr(data, tag); else throw new Error('Unsupported tag: ' + tag); }; Node.prototype._isNumstr = function isNumstr(str) { return /^[0-9 ]*$/.test(str); }; Node.prototype._isPrintstr = function isPrintstr(str) { return /^[A-Za-z0-9 '\(\)\+,\-\.\/:=\?]*$/.test(str); }; },{"../base":48,"minimalistic-assert":382}],50:[function(_dereq_,module,exports){ var inherits = _dereq_('inherits'); function Reporter(options) { this._reporterState = { obj: null, path: [], options: options || {}, errors: [] }; } exports.Reporter = Reporter; Reporter.prototype.isError = function isError(obj) { return obj instanceof ReporterError; }; Reporter.prototype.save = function save() { var state = this._reporterState; return { obj: state.obj, pathLen: state.path.length }; }; Reporter.prototype.restore = function restore(data) { var state = this._reporterState; state.obj = data.obj; state.path = state.path.slice(0, data.pathLen); }; Reporter.prototype.enterKey = function enterKey(key) { return this._reporterState.path.push(key); }; Reporter.prototype.exitKey = function exitKey(index) { var state = this._reporterState; state.path = state.path.slice(0, index - 1); }; Reporter.prototype.leaveKey = function leaveKey(index, key, value) { var state = this._reporterState; this.exitKey(index); if (state.obj !== null) state.obj[key] = value; }; Reporter.prototype.path = function path() { return this._reporterState.path.join('/'); }; Reporter.prototype.enterObject = function enterObject() { var state = this._reporterState; var prev = state.obj; state.obj = {}; return prev; }; Reporter.prototype.leaveObject = function leaveObject(prev) { var state = this._reporterState; var now = state.obj; state.obj = prev; return now; }; Reporter.prototype.error = function error(msg) { var err; var state = this._reporterState; var inherited = msg instanceof ReporterError; if (inherited) { err = msg; } else { err = new ReporterError(state.path.map(function(elem) { return '[' + JSON.stringify(elem) + ']'; }).join(''), msg.message || msg, msg.stack); } if (!state.options.partial) throw err; if (!inherited) state.errors.push(err); return err; }; Reporter.prototype.wrapResult = function wrapResult(result) { var state = this._reporterState; if (!state.options.partial) return result; return { result: this.isError(result) ? null : result, errors: state.errors }; }; function ReporterError(path, msg) { this.path = path; this.rethrow(msg); }; inherits(ReporterError, Error); ReporterError.prototype.rethrow = function rethrow(msg) { this.message = msg + ' at: ' + (this.path || '(shallow)'); if (Error.captureStackTrace) Error.captureStackTrace(this, ReporterError); if (!this.stack) { try { // IE only adds stack when thrown throw new Error(this.message); } catch (e) { this.stack = e.stack; } } return this; }; },{"inherits":332}],51:[function(_dereq_,module,exports){ var constants = _dereq_('../constants'); exports.tagClass = { 0: 'universal', 1: 'application', 2: 'context', 3: 'private' }; exports.tagClassByName = constants._reverse(exports.tagClass); exports.tag = { 0x00: 'end', 0x01: 'bool', 0x02: 'int', 0x03: 'bitstr', 0x04: 'octstr', 0x05: 'null_', 0x06: 'objid', 0x07: 'objDesc', 0x08: 'external', 0x09: 'real', 0x0a: 'enum', 0x0b: 'embed', 0x0c: 'utf8str', 0x0d: 'relativeOid', 0x10: 'seq', 0x11: 'set', 0x12: 'numstr', 0x13: 'printstr', 0x14: 't61str', 0x15: 'videostr', 0x16: 'ia5str', 0x17: 'utctime', 0x18: 'gentime', 0x19: 'graphstr', 0x1a: 'iso646str', 0x1b: 'genstr', 0x1c: 'unistr', 0x1d: 'charstr', 0x1e: 'bmpstr' }; exports.tagByName = constants._reverse(exports.tag); },{"../constants":52}],52:[function(_dereq_,module,exports){ var constants = exports; // Helper constants._reverse = function reverse(map) { var res = {}; Object.keys(map).forEach(function(key) { // Convert key to integer if it is stringified if ((key | 0) == key) key = key | 0; var value = map[key]; res[value] = key; }); return res; }; constants.der = _dereq_('./der'); },{"./der":51}],53:[function(_dereq_,module,exports){ var inherits = _dereq_('inherits'); var asn1 = _dereq_('../../asn1'); var base = asn1.base; var bignum = asn1.bignum; // Import DER constants var der = asn1.constants.der; function DERDecoder(entity) { this.enc = 'der'; this.name = entity.name; this.entity = entity; // Construct base tree this.tree = new DERNode(); this.tree._init(entity.body); }; module.exports = DERDecoder; DERDecoder.prototype.decode = function decode(data, options) { if (!(data instanceof base.DecoderBuffer)) data = new base.DecoderBuffer(data, options); return this.tree._decode(data, options); }; // Tree methods function DERNode(parent) { base.Node.call(this, 'der', parent); } inherits(DERNode, base.Node); DERNode.prototype._peekTag = function peekTag(buffer, tag, any) { if (buffer.isEmpty()) return false; var state = buffer.save(); var decodedTag = derDecodeTag(buffer, 'Failed to peek tag: "' + tag + '"'); if (buffer.isError(decodedTag)) return decodedTag; buffer.restore(state); return decodedTag.tag === tag || decodedTag.tagStr === tag || (decodedTag.tagStr + 'of') === tag || any; }; DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) { var decodedTag = derDecodeTag(buffer, 'Failed to decode tag of "' + tag + '"'); if (buffer.isError(decodedTag)) return decodedTag; var len = derDecodeLen(buffer, decodedTag.primitive, 'Failed to get length of "' + tag + '"'); // Failure if (buffer.isError(len)) return len; if (!any && decodedTag.tag !== tag && decodedTag.tagStr !== tag && decodedTag.tagStr + 'of' !== tag) { return buffer.error('Failed to match tag: "' + tag + '"'); } if (decodedTag.primitive || len !== null) return buffer.skip(len, 'Failed to match body of: "' + tag + '"'); // Indefinite length... find END tag var state = buffer.save(); var res = this._skipUntilEnd( buffer, 'Failed to skip indefinite length body: "' + this.tag + '"'); if (buffer.isError(res)) return res; len = buffer.offset - state.offset; buffer.restore(state); return buffer.skip(len, 'Failed to match body of: "' + tag + '"'); }; DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer, fail) { while (true) { var tag = derDecodeTag(buffer, fail); if (buffer.isError(tag)) return tag; var len = derDecodeLen(buffer, tag.primitive, fail); if (buffer.isError(len)) return len; var res; if (tag.primitive || len !== null) res = buffer.skip(len) else res = this._skipUntilEnd(buffer, fail); // Failure if (buffer.isError(res)) return res; if (tag.tagStr === 'end') break; } }; DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder, options) { var result = []; while (!buffer.isEmpty()) { var possibleEnd = this._peekTag(buffer, 'end'); if (buffer.isError(possibleEnd)) return possibleEnd; var res = decoder.decode(buffer, 'der', options); if (buffer.isError(res) && possibleEnd) break; result.push(res); } return result; }; DERNode.prototype._decodeStr = function decodeStr(buffer, tag) { if (tag === 'bitstr') { var unused = buffer.readUInt8(); if (buffer.isError(unused)) return unused; return { unused: unused, data: buffer.raw() }; } else if (tag === 'bmpstr') { var raw = buffer.raw(); if (raw.length % 2 === 1) return buffer.error('Decoding of string type: bmpstr length mismatch'); var str = ''; for (var i = 0; i < raw.length / 2; i++) { str += String.fromCharCode(raw.readUInt16BE(i * 2)); } return str; } else if (tag === 'numstr') { var numstr = buffer.raw().toString('ascii'); if (!this._isNumstr(numstr)) { return buffer.error('Decoding of string type: ' + 'numstr unsupported characters'); } return numstr; } else if (tag === 'octstr') { return buffer.raw(); } else if (tag === 'objDesc') { return buffer.raw(); } else if (tag === 'printstr') { var printstr = buffer.raw().toString('ascii'); if (!this._isPrintstr(printstr)) { return buffer.error('Decoding of string type: ' + 'printstr unsupported characters'); } return printstr; } else if (/str$/.test(tag)) { return buffer.raw().toString(); } else { return buffer.error('Decoding of string type: ' + tag + ' unsupported'); } }; DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) { var result; var identifiers = []; var ident = 0; while (!buffer.isEmpty()) { var subident = buffer.readUInt8(); ident <<= 7; ident |= subident & 0x7f; if ((subident & 0x80) === 0) { identifiers.push(ident); ident = 0; } } if (subident & 0x80) identifiers.push(ident); var first = (identifiers[0] / 40) | 0; var second = identifiers[0] % 40; if (relative) result = identifiers; else result = [first, second].concat(identifiers.slice(1)); if (values) { var tmp = values[result.join(' ')]; if (tmp === undefined) tmp = values[result.join('.')]; if (tmp !== undefined) result = tmp; } return result; }; DERNode.prototype._decodeTime = function decodeTime(buffer, tag) { var str = buffer.raw().toString(); if (tag === 'gentime') { var year = str.slice(0, 4) | 0; var mon = str.slice(4, 6) | 0; var day = str.slice(6, 8) | 0; var hour = str.slice(8, 10) | 0; var min = str.slice(10, 12) | 0; var sec = str.slice(12, 14) | 0; } else if (tag === 'utctime') { var year = str.slice(0, 2) | 0; var mon = str.slice(2, 4) | 0; var day = str.slice(4, 6) | 0; var hour = str.slice(6, 8) | 0; var min = str.slice(8, 10) | 0; var sec = str.slice(10, 12) | 0; if (year < 70) year = 2000 + year; else year = 1900 + year; } else { return buffer.error('Decoding ' + tag + ' time is not supported yet'); } return Date.UTC(year, mon - 1, day, hour, min, sec, 0); }; DERNode.prototype._decodeNull = function decodeNull(buffer) { return null; }; DERNode.prototype._decodeBool = function decodeBool(buffer) { var res = buffer.readUInt8(); if (buffer.isError(res)) return res; else return res !== 0; }; DERNode.prototype._decodeInt = function decodeInt(buffer, values) { // Bigint, return as it is (assume big endian) var raw = buffer.raw(); var res = new bignum(raw); if (values) res = values[res.toString(10)] || res; return res; }; DERNode.prototype._use = function use(entity, obj) { if (typeof entity === 'function') entity = entity(obj); return entity._getDecoder('der').tree; }; // Utility methods function derDecodeTag(buf, fail) { var tag = buf.readUInt8(fail); if (buf.isError(tag)) return tag; var cls = der.tagClass[tag >> 6]; var primitive = (tag & 0x20) === 0; // Multi-octet tag - load if ((tag & 0x1f) === 0x1f) { var oct = tag; tag = 0; while ((oct & 0x80) === 0x80) { oct = buf.readUInt8(fail); if (buf.isError(oct)) return oct; tag <<= 7; tag |= oct & 0x7f; } } else { tag &= 0x1f; } var tagStr = der.tag[tag]; return { cls: cls, primitive: primitive, tag: tag, tagStr: tagStr }; } function derDecodeLen(buf, primitive, fail) { var len = buf.readUInt8(fail); if (buf.isError(len)) return len; // Indefinite form if (!primitive && len === 0x80) return null; // Definite form if ((len & 0x80) === 0) { // Short form return len; } // Long form var num = len & 0x7f; if (num > 4) return buf.error('length octect is too long'); len = 0; for (var i = 0; i < num; i++) { len <<= 8; var j = buf.readUInt8(fail); if (buf.isError(j)) return j; len |= j; } return len; } },{"../../asn1":45,"inherits":332}],54:[function(_dereq_,module,exports){ var decoders = exports; decoders.der = _dereq_('./der'); decoders.pem = _dereq_('./pem'); },{"./der":53,"./pem":55}],55:[function(_dereq_,module,exports){ var inherits = _dereq_('inherits'); var Buffer = _dereq_('buffer').Buffer; var DERDecoder = _dereq_('./der'); function PEMDecoder(entity) { DERDecoder.call(this, entity); this.enc = 'pem'; }; inherits(PEMDecoder, DERDecoder); module.exports = PEMDecoder; PEMDecoder.prototype.decode = function decode(data, options) { var lines = data.toString().split(/[\r\n]+/g); var label = options.label.toUpperCase(); var re = /^-----(BEGIN|END) ([^-]+)-----$/; var start = -1; var end = -1; for (var i = 0; i < lines.length; i++) { var match = lines[i].match(re); if (match === null) continue; if (match[2] !== label) continue; if (start === -1) { if (match[1] !== 'BEGIN') break; start = i; } else { if (match[1] !== 'END') break; end = i; break; } } if (start === -1 || end === -1) throw new Error('PEM section not found for: ' + label); var base64 = lines.slice(start + 1, end).join(''); // Remove excessive symbols base64.replace(/[^a-z0-9\+\/=]+/gi, ''); var input = new Buffer(base64, 'base64'); return DERDecoder.prototype.decode.call(this, input, options); }; },{"./der":53,"buffer":142,"inherits":332}],56:[function(_dereq_,module,exports){ var inherits = _dereq_('inherits'); var Buffer = _dereq_('buffer').Buffer; var asn1 = _dereq_('../../asn1'); var base = asn1.base; // Import DER constants var der = asn1.constants.der; function DEREncoder(entity) { this.enc = 'der'; this.name = entity.name; this.entity = entity; // Construct base tree this.tree = new DERNode(); this.tree._init(entity.body); }; module.exports = DEREncoder; DEREncoder.prototype.encode = function encode(data, reporter) { return this.tree._encode(data, reporter).join(); }; // Tree methods function DERNode(parent) { base.Node.call(this, 'der', parent); } inherits(DERNode, base.Node); DERNode.prototype._encodeComposite = function encodeComposite(tag, primitive, cls, content) { var encodedTag = encodeTag(tag, primitive, cls, this.reporter); // Short form if (content.length < 0x80) { var header = new Buffer(2); header[0] = encodedTag; header[1] = content.length; return this._createEncoderBuffer([ header, content ]); } // Long form // Count octets required to store length var lenOctets = 1; for (var i = content.length; i >= 0x100; i >>= 8) lenOctets++; var header = new Buffer(1 + 1 + lenOctets); header[0] = encodedTag; header[1] = 0x80 | lenOctets; for (var i = 1 + lenOctets, j = content.length; j > 0; i--, j >>= 8) header[i] = j & 0xff; return this._createEncoderBuffer([ header, content ]); }; DERNode.prototype._encodeStr = function encodeStr(str, tag) { if (tag === 'bitstr') { return this._createEncoderBuffer([ str.unused | 0, str.data ]); } else if (tag === 'bmpstr') { var buf = new Buffer(str.length * 2); for (var i = 0; i < str.length; i++) { buf.writeUInt16BE(str.charCodeAt(i), i * 2); } return this._createEncoderBuffer(buf); } else if (tag === 'numstr') { if (!this._isNumstr(str)) { return this.reporter.error('Encoding of string type: numstr supports ' + 'only digits and space'); } return this._createEncoderBuffer(str); } else if (tag === 'printstr') { if (!this._isPrintstr(str)) { return this.reporter.error('Encoding of string type: printstr supports ' + 'only latin upper and lower case letters, ' + 'digits, space, apostrophe, left and rigth ' + 'parenthesis, plus sign, comma, hyphen, ' + 'dot, slash, colon, equal sign, ' + 'question mark'); } return this._createEncoderBuffer(str); } else if (/str$/.test(tag)) { return this._createEncoderBuffer(str); } else if (tag === 'objDesc') { return this._createEncoderBuffer(str); } else { return this.reporter.error('Encoding of string type: ' + tag + ' unsupported'); } }; DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) { if (typeof id === 'string') { if (!values) return this.reporter.error('string objid given, but no values map found'); if (!values.hasOwnProperty(id)) return this.reporter.error('objid not found in values map'); id = values[id].split(/[\s\.]+/g); for (var i = 0; i < id.length; i++) id[i] |= 0; } else if (Array.isArray(id)) { id = id.slice(); for (var i = 0; i < id.length; i++) id[i] |= 0; } if (!Array.isArray(id)) { return this.reporter.error('objid() should be either array or string, ' + 'got: ' + JSON.stringify(id)); } if (!relative) { if (id[1] >= 40) return this.reporter.error('Second objid identifier OOB'); id.splice(0, 2, id[0] * 40 + id[1]); } // Count number of octets var size = 0; for (var i = 0; i < id.length; i++) { var ident = id[i]; for (size++; ident >= 0x80; ident >>= 7) size++; } var objid = new Buffer(size); var offset = objid.length - 1; for (var i = id.length - 1; i >= 0; i--) { var ident = id[i]; objid[offset--] = ident & 0x7f; while ((ident >>= 7) > 0) objid[offset--] = 0x80 | (ident & 0x7f); } return this._createEncoderBuffer(objid); }; function two(num) { if (num < 10) return '0' + num; else return num; } DERNode.prototype._encodeTime = function encodeTime(time, tag) { var str; var date = new Date(time); if (tag === 'gentime') { str = [ two(date.getFullYear()), two(date.getUTCMonth() + 1), two(date.getUTCDate()), two(date.getUTCHours()), two(date.getUTCMinutes()), two(date.getUTCSeconds()), 'Z' ].join(''); } else if (tag === 'utctime') { str = [ two(date.getFullYear() % 100), two(date.getUTCMonth() + 1), two(date.getUTCDate()), two(date.getUTCHours()), two(date.getUTCMinutes()), two(date.getUTCSeconds()), 'Z' ].join(''); } else { this.reporter.error('Encoding ' + tag + ' time is not supported yet'); } return this._encodeStr(str, 'octstr'); }; DERNode.prototype._encodeNull = function encodeNull() { return this._createEncoderBuffer(''); }; DERNode.prototype._encodeInt = function encodeInt(num, values) { if (typeof num === 'string') { if (!values) return this.reporter.error('String int or enum given, but no values map'); if (!values.hasOwnProperty(num)) { return this.reporter.error('Values map doesn\'t contain: ' + JSON.stringify(num)); } num = values[num]; } // Bignum, assume big endian if (typeof num !== 'number' && !Buffer.isBuffer(num)) { var numArray = num.toArray(); if (!num.sign && numArray[0] & 0x80) { numArray.unshift(0); } num = new Buffer(numArray); } if (Buffer.isBuffer(num)) { var size = num.length; if (num.length === 0) size++; var out = new Buffer(size); num.copy(out); if (num.length === 0) out[0] = 0 return this._createEncoderBuffer(out); } if (num < 0x80) return this._createEncoderBuffer(num); if (num < 0x100) return this._createEncoderBuffer([0, num]); var size = 1; for (var i = num; i >= 0x100; i >>= 8) size++; var out = new Array(size); for (var i = out.length - 1; i >= 0; i--) { out[i] = num & 0xff; num >>= 8; } if(out[0] & 0x80) { out.unshift(0); } return this._createEncoderBuffer(new Buffer(out)); }; DERNode.prototype._encodeBool = function encodeBool(value) { return this._createEncoderBuffer(value ? 0xff : 0); }; DERNode.prototype._use = function use(entity, obj) { if (typeof entity === 'function') entity = entity(obj); return entity._getEncoder('der').tree; }; DERNode.prototype._skipDefault = function skipDefault(dataBuffer, reporter, parent) { var state = this._baseState; var i; if (state['default'] === null) return false; var data = dataBuffer.join(); if (state.defaultBuffer === undefined) state.defaultBuffer = this._encodeValue(state['default'], reporter, parent).join(); if (data.length !== state.defaultBuffer.length) return false; for (i=0; i < data.length; i++) if (data[i] !== state.defaultBuffer[i]) return false; return true; }; // Utility methods function encodeTag(tag, primitive, cls, reporter) { var res; if (tag === 'seqof') tag = 'seq'; else if (tag === 'setof') tag = 'set'; if (der.tagByName.hasOwnProperty(tag)) res = der.tagByName[tag]; else if (typeof tag === 'number' && (tag | 0) === tag) res = tag; else return reporter.error('Unknown tag: ' + tag); if (res >= 0x1f) return reporter.error('Multi-octet tag encoding unsupported'); if (!primitive) res |= 0x20; res |= (der.tagClassByName[cls || 'universal'] << 6); return res; } },{"../../asn1":45,"buffer":142,"inherits":332}],57:[function(_dereq_,module,exports){ var encoders = exports; encoders.der = _dereq_('./der'); encoders.pem = _dereq_('./pem'); },{"./der":56,"./pem":58}],58:[function(_dereq_,module,exports){ var inherits = _dereq_('inherits'); var DEREncoder = _dereq_('./der'); function PEMEncoder(entity) { DEREncoder.call(this, entity); this.enc = 'pem'; }; inherits(PEMEncoder, DEREncoder); module.exports = PEMEncoder; PEMEncoder.prototype.encode = function encode(data, options) { var buf = DEREncoder.prototype.encode.call(this, data); var p = buf.toString('base64'); var out = [ '-----BEGIN ' + options.label + '-----' ]; for (var i = 0; i < p.length; i += 64) out.push(p.slice(i, i + 64)); out.push('-----END ' + options.label + '-----'); return out.join('\n'); }; },{"./der":56,"inherits":332}],59:[function(_dereq_,module,exports){ (function (global){ 'use strict'; // compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js // original notice: /*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh * @license MIT */ function compare(a, b) { if (a === b) { return 0; } var x = a.length; var y = b.length; for (var i = 0, len = Math.min(x, y); i < len; ++i) { if (a[i] !== b[i]) { x = a[i]; y = b[i]; break; } } if (x < y) { return -1; } if (y < x) { return 1; } return 0; } function isBuffer(b) { if (global.Buffer && typeof global.Buffer.isBuffer === 'function') { return global.Buffer.isBuffer(b); } return !!(b != null && b._isBuffer); } // based on node assert, original notice: // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 // // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! // // Originally from narwhal.js (http://narwhaljs.org) // Copyright (c) 2009 Thomas Robinson <280north.com> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the 'Software'), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = _dereq_('util/'); var hasOwn = Object.prototype.hasOwnProperty; var pSlice = Array.prototype.slice; var functionsHaveNames = (function () { return function foo() {}.name === 'foo'; }()); function pToString (obj) { return Object.prototype.toString.call(obj); } function isView(arrbuf) { if (isBuffer(arrbuf)) { return false; } if (typeof global.ArrayBuffer !== 'function') { return false; } if (typeof ArrayBuffer.isView === 'function') { return ArrayBuffer.isView(arrbuf); } if (!arrbuf) { return false; } if (arrbuf instanceof DataView) { return true; } if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) { return true; } return false; } // 1. The assert module provides functions that throw // AssertionError's when particular conditions are not met. The // assert module must conform to the following interface. var assert = module.exports = ok; // 2. The AssertionError is defined in assert. // new assert.AssertionError({ message: message, // actual: actual, // expected: expected }) var regex = /\s*function\s+([^\(\s]*)\s*/; // based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js function getName(func) { if (!util.isFunction(func)) { return; } if (functionsHaveNames) { return func.name; } var str = func.toString(); var match = str.match(regex); return match && match[1]; } assert.AssertionError = function AssertionError(options) { this.name = 'AssertionError'; this.actual = options.actual; this.expected = options.expected; this.operator = options.operator; if (options.message) { this.message = options.message; this.generatedMessage = false; } else { this.message = getMessage(this); this.generatedMessage = true; } var stackStartFunction = options.stackStartFunction || fail; if (Error.captureStackTrace) { Error.captureStackTrace(this, stackStartFunction); } else { // non v8 browsers so we can have a stacktrace var err = new Error(); if (err.stack) { var out = err.stack; // try to strip useless frames var fn_name = getName(stackStartFunction); var idx = out.indexOf('\n' + fn_name); if (idx >= 0) { // once we have located the function frame // we need to strip out everything before it (and its line) var next_line = out.indexOf('\n', idx + 1); out = out.substring(next_line + 1); } this.stack = out; } } }; // assert.AssertionError instanceof Error util.inherits(assert.AssertionError, Error); function truncate(s, n) { if (typeof s === 'string') { return s.length < n ? s : s.slice(0, n); } else { return s; } } function inspect(something) { if (functionsHaveNames || !util.isFunction(something)) { return util.inspect(something); } var rawname = getName(something); var name = rawname ? ': ' + rawname : ''; return '[Function' + name + ']'; } function getMessage(self) { return truncate(inspect(self.actual), 128) + ' ' + self.operator + ' ' + truncate(inspect(self.expected), 128); } // At present only the three keys mentioned above are used and // understood by the spec. Implementations or sub modules can pass // other keys to the AssertionError's constructor - they will be // ignored. // 3. All of the following functions must throw an AssertionError // when a corresponding condition is not met, with a message that // may be undefined if not provided. All assertion methods provide // both the actual and expected values to the assertion error for // display purposes. function fail(actual, expected, message, operator, stackStartFunction) { throw new assert.AssertionError({ message: message, actual: actual, expected: expected, operator: operator, stackStartFunction: stackStartFunction }); } // EXTENSION! allows for well behaved errors defined elsewhere. assert.fail = fail; // 4. Pure assertion tests whether a value is truthy, as determined // by !!guard. // assert.ok(guard, message_opt); // This statement is equivalent to assert.equal(true, !!guard, // message_opt);. To test strictly for the value true, use // assert.strictEqual(true, guard, message_opt);. function ok(value, message) { if (!value) fail(value, true, message, '==', assert.ok); } assert.ok = ok; // 5. The equality assertion tests shallow, coercive equality with // ==. // assert.equal(actual, expected, message_opt); assert.equal = function equal(actual, expected, message) { if (actual != expected) fail(actual, expected, message, '==', assert.equal); }; // 6. The non-equality assertion tests for whether two objects are not equal // with != assert.notEqual(actual, expected, message_opt); assert.notEqual = function notEqual(actual, expected, message) { if (actual == expected) { fail(actual, expected, message, '!=', assert.notEqual); } }; // 7. The equivalence assertion tests a deep equality relation. // assert.deepEqual(actual, expected, message_opt); assert.deepEqual = function deepEqual(actual, expected, message) { if (!_deepEqual(actual, expected, false)) { fail(actual, expected, message, 'deepEqual', assert.deepEqual); } }; assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) { if (!_deepEqual(actual, expected, true)) { fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual); } }; function _deepEqual(actual, expected, strict, memos) { // 7.1. All identical values are equivalent, as determined by ===. if (actual === expected) { return true; } else if (isBuffer(actual) && isBuffer(expected)) { return compare(actual, expected) === 0; // 7.2. If the expected value is a Date object, the actual value is // equivalent if it is also a Date object that refers to the same time. } else if (util.isDate(actual) && util.isDate(expected)) { return actual.getTime() === expected.getTime(); // 7.3 If the expected value is a RegExp object, the actual value is // equivalent if it is also a RegExp object with the same source and // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). } else if (util.isRegExp(actual) && util.isRegExp(expected)) { return actual.source === expected.source && actual.global === expected.global && actual.multiline === expected.multiline && actual.lastIndex === expected.lastIndex && actual.ignoreCase === expected.ignoreCase; // 7.4. Other pairs that do not both pass typeof value == 'object', // equivalence is determined by ==. } else if ((actual === null || typeof actual !== 'object') && (expected === null || typeof expected !== 'object')) { return strict ? actual === expected : actual == expected; // If both values are instances of typed arrays, wrap their underlying // ArrayBuffers in a Buffer each to increase performance // This optimization requires the arrays to have the same type as checked by // Object.prototype.toString (aka pToString). Never perform binary // comparisons for Float*Arrays, though, since e.g. +0 === -0 but their // bit patterns are not identical. } else if (isView(actual) && isView(expected) && pToString(actual) === pToString(expected) && !(actual instanceof Float32Array || actual instanceof Float64Array)) { return compare(new Uint8Array(actual.buffer), new Uint8Array(expected.buffer)) === 0; // 7.5 For all other Object pairs, including Array objects, equivalence is // determined by having the same number of owned properties (as verified // with Object.prototype.hasOwnProperty.call), the same set of keys // (although not necessarily the same order), equivalent values for every // corresponding key, and an identical 'prototype' property. Note: this // accounts for both named and indexed properties on Arrays. } else if (isBuffer(actual) !== isBuffer(expected)) { return false; } else { memos = memos || {actual: [], expected: []}; var actualIndex = memos.actual.indexOf(actual); if (actualIndex !== -1) { if (actualIndex === memos.expected.indexOf(expected)) { return true; } } memos.actual.push(actual); memos.expected.push(expected); return objEquiv(actual, expected, strict, memos); } } function isArguments(object) { return Object.prototype.toString.call(object) == '[object Arguments]'; } function objEquiv(a, b, strict, actualVisitedObjects) { if (a === null || a === undefined || b === null || b === undefined) return false; // if one is a primitive, the other must be same if (util.isPrimitive(a) || util.isPrimitive(b)) return a === b; if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) return false; var aIsArgs = isArguments(a); var bIsArgs = isArguments(b); if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) return false; if (aIsArgs) { a = pSlice.call(a); b = pSlice.call(b); return _deepEqual(a, b, strict); } var ka = objectKeys(a); var kb = objectKeys(b); var key, i; // having the same number of owned properties (keys incorporates // hasOwnProperty) if (ka.length !== kb.length) return false; //the same set of keys (although not necessarily the same order), ka.sort(); kb.sort(); //~~~cheap key test for (i = ka.length - 1; i >= 0; i--) { if (ka[i] !== kb[i]) return false; } //equivalent values for every corresponding key, and //~~~possibly expensive deep test for (i = ka.length - 1; i >= 0; i--) { key = ka[i]; if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects)) return false; } return true; } // 8. The non-equivalence assertion tests for any deep inequality. // assert.notDeepEqual(actual, expected, message_opt); assert.notDeepEqual = function notDeepEqual(actual, expected, message) { if (_deepEqual(actual, expected, false)) { fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); } }; assert.notDeepStrictEqual = notDeepStrictEqual; function notDeepStrictEqual(actual, expected, message) { if (_deepEqual(actual, expected, true)) { fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual); } } // 9. The strict equality assertion tests strict equality, as determined by ===. // assert.strictEqual(actual, expected, message_opt); assert.strictEqual = function strictEqual(actual, expected, message) { if (actual !== expected) { fail(actual, expected, message, '===', assert.strictEqual); } }; // 10. The strict non-equality assertion tests for strict inequality, as // determined by !==. assert.notStrictEqual(actual, expected, message_opt); assert.notStrictEqual = function notStrictEqual(actual, expected, message) { if (actual === expected) { fail(actual, expected, message, '!==', assert.notStrictEqual); } }; function expectedException(actual, expected) { if (!actual || !expected) { return false; } if (Object.prototype.toString.call(expected) == '[object RegExp]') { return expected.test(actual); } try { if (actual instanceof expected) { return true; } } catch (e) { // Ignore. The instanceof check doesn't work for arrow functions. } if (Error.isPrototypeOf(expected)) { return false; } return expected.call({}, actual) === true; } function _tryBlock(block) { var error; try { block(); } catch (e) { error = e; } return error; } function _throws(shouldThrow, block, expected, message) { var actual; if (typeof block !== 'function') { throw new TypeError('"block" argument must be a function'); } if (typeof expected === 'string') { message = expected; expected = null; } actual = _tryBlock(block); message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + (message ? ' ' + message : '.'); if (shouldThrow && !actual) { fail(actual, expected, 'Missing expected exception' + message); } var userProvidedMessage = typeof message === 'string'; var isUnwantedException = !shouldThrow && util.isError(actual); var isUnexpectedException = !shouldThrow && actual && !expected; if ((isUnwantedException && userProvidedMessage && expectedException(actual, expected)) || isUnexpectedException) { fail(actual, expected, 'Got unwanted exception' + message); } if ((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) { throw actual; } } // 11. Expected to throw an error: // assert.throws(block, Error_opt, message_opt); assert.throws = function(block, /*optional*/error, /*optional*/message) { _throws(true, block, error, message); }; // EXTENSION! This is annoying to write outside this module. assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { _throws(false, block, error, message); }; assert.ifError = function(err) { if (err) throw err; }; var objectKeys = Object.keys || function (obj) { var keys = []; for (var key in obj) { if (hasOwn.call(obj, key)) keys.push(key); } return keys; }; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"util/":468}],60:[function(_dereq_,module,exports){ 'use strict'; module.exports = _dereq_('./lib/AsyncEventEmitter'); },{"./lib/AsyncEventEmitter":61}],61:[function(_dereq_,module,exports){ 'use strict'; var EventEmitter = _dereq_('events').EventEmitter, util = _dereq_('util'), eachSeries = _dereq_('async/eachSeries'), AsyncEventEmitter; module.exports = exports = AsyncEventEmitter = function AsyncEventEmitter () { EventEmitter.call(this); }; util.inherits(AsyncEventEmitter, EventEmitter); /* Public methods ============================================================================= */ AsyncEventEmitter.prototype.emit = function(event, data, callback) { var self = this, listeners = self._events[event] || []; // Optional data argument if(!callback && typeof data === 'function') { callback = data; data = undefined; } // Special treatment of internal newListener and removeListener events if(event === 'newListener' || event === 'removeListener') { data = { event: data, fn: callback }; callback = undefined; } // A single listener is just a function not an array... listeners = Array.isArray(listeners) ? listeners : [listeners]; eachSeries(listeners, function (fn, next) { var err; // Support synchronous functions if(fn.length < 2) { try { fn.call(self, data); } catch (e) { err = e; } return next(err); } // Async fn.call(self, data, next); }, callback); return self; }; AsyncEventEmitter.prototype.once = function (type, listener) { var self = this, g; if (typeof listener !== 'function') { throw new TypeError('listener must be a function'); } // Hack to support set arity if(listener.length >= 2) { g = function (e, next) { self.removeListener(type, g); listener(e, next); }; } else { g = function (e) { self.removeListener(type, g); listener(e); }; } g.listener = listener; self.on(type, g); return self; }; AsyncEventEmitter.prototype.first = function(event, listener) { var listeners = this._events[event] || []; // Contract if(typeof listener !== 'function') { throw new TypeError('listener must be a function'); } // Listeners are not always an array if(!Array.isArray(listeners)) { this._events[event] = listeners = [listeners]; } listeners.unshift(listener); return this; }; AsyncEventEmitter.prototype.at = function(event, index, listener) { var listeners = this._events[event] || []; // Contract if(typeof listener !== 'function') { throw new TypeError('listener must be a function'); } if(typeof index !== 'number' || index < 0) { throw new TypeError('index must be a non-negative integer'); } // Listeners are not always an array if(!Array.isArray(listeners)) { this._events[event] = listeners = [listeners]; } listeners.splice(index, 0, listener); return this; }; AsyncEventEmitter.prototype.before = function(event, target, listener) { return this._beforeOrAfter(event, target, listener); }; AsyncEventEmitter.prototype.after = function(event, target, listener) { return this._beforeOrAfter(event, target, listener, 'after'); }; /* Private methods ============================================================================= */ AsyncEventEmitter.prototype._beforeOrAfter = function(event, target, listener, beforeOrAfter) { var listeners = this._events[event] || [], i, index, add = beforeOrAfter === 'after' ? 1 : 0; // Contract if(typeof listener !== 'function') { throw new TypeError('listener must be a function'); } if(typeof target !== 'function') { throw new TypeError('target must be a function'); } // Listeners are not always an array if(!Array.isArray(listeners)) { this._events[event] = listeners = [listeners]; } index = listeners.length; for(i = listeners.length; i--;) { if(listeners[i] === target) { index = i + add; break; } } listeners.splice(index, 0, listener); return this; }; },{"async/eachSeries":64,"events":314,"util":468}],62:[function(_dereq_,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = asyncify; var _isObject = _dereq_('lodash/isObject'); var _isObject2 = _interopRequireDefault(_isObject); var _initialParams = _dereq_('./internal/initialParams'); var _initialParams2 = _interopRequireDefault(_initialParams); var _setImmediate = _dereq_('./internal/setImmediate'); var _setImmediate2 = _interopRequireDefault(_setImmediate); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Take a sync function and make it async, passing its return value to a * callback. This is useful for plugging sync functions into a waterfall, * series, or other async functions. Any arguments passed to the generated * function will be passed to the wrapped function (except for the final * callback argument). Errors thrown will be passed to the callback. * * If the function passed to `asyncify` returns a Promise, that promises's * resolved/rejected state will be used to call the callback, rather than simply * the synchronous return value. * * This also means you can asyncify ES2017 `async` functions. * * @name asyncify * @static * @memberOf module:Utils * @method * @alias wrapSync * @category Util * @param {Function} func - The synchronous function, or Promise-returning * function to convert to an {@link AsyncFunction}. * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be * invoked with `(args..., callback)`. * @example * * // passing a regular synchronous function * async.waterfall([ * async.apply(fs.readFile, filename, "utf8"), * async.asyncify(JSON.parse), * function (data, next) { * // data is the result of parsing the text. * // If there was a parsing error, it would have been caught. * } * ], callback); * * // passing a function returning a promise * async.waterfall([ * async.apply(fs.readFile, filename, "utf8"), * async.asyncify(function (contents) { * return db.model.create(contents); * }), * function (model, next) { * // `model` is the instantiated model object. * // If there was an error, this function would be skipped. * } * ], callback); * * // es2017 example, though `asyncify` is not needed if your JS environment * // supports async functions out of the box * var q = async.queue(async.asyncify(async function(file) { * var intermediateStep = await processFile(file); * return await somePromise(intermediateStep) * })); * * q.push(files); */ function asyncify(func) { return (0, _initialParams2.default)(function (args, callback) { var result; try { result = func.apply(this, args); } catch (e) { return callback(e); } // if result is Promise object if ((0, _isObject2.default)(result) && typeof result.then === 'function') { result.then(function (value) { invokeCallback(callback, null, value); }, function (err) { invokeCallback(callback, err.message ? err : new Error(err)); }); } else { callback(null, result); } }); } function invokeCallback(callback, error, value) { try { callback(error, value); } catch (e) { (0, _setImmediate2.default)(rethrow, e); } } function rethrow(error) { throw error; } module.exports = exports['default']; },{"./internal/initialParams":69,"./internal/setImmediate":73,"lodash/isObject":374}],63:[function(_dereq_,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = eachLimit; var _eachOfLimit = _dereq_('./internal/eachOfLimit'); var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); var _withoutIndex = _dereq_('./internal/withoutIndex'); var _withoutIndex2 = _interopRequireDefault(_withoutIndex); var _wrapAsync = _dereq_('./internal/wrapAsync'); var _wrapAsync2 = _interopRequireDefault(_wrapAsync); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time. * * @name eachLimit * @static * @memberOf module:Collections * @method * @see [async.each]{@link module:Collections.each} * @alias forEachLimit * @category Collection * @param {Array|Iterable|Object} coll - A collection to iterate over. * @param {number} limit - The maximum number of async operations at a time. * @param {AsyncFunction} iteratee - An async function to apply to each item in * `coll`. * The array index is not passed to the iteratee. * If you need the index, use `eachOfLimit`. * Invoked with (item, callback). * @param {Function} [callback] - A callback which is called when all * `iteratee` functions have finished, or an error occurs. Invoked with (err). */ function eachLimit(coll, limit, iteratee, callback) { (0, _eachOfLimit2.default)(limit)(coll, (0, _withoutIndex2.default)((0, _wrapAsync2.default)(iteratee)), callback); } module.exports = exports['default']; },{"./internal/eachOfLimit":67,"./internal/withoutIndex":75,"./internal/wrapAsync":76}],64:[function(_dereq_,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _eachLimit = _dereq_('./eachLimit'); var _eachLimit2 = _interopRequireDefault(_eachLimit); var _doLimit = _dereq_('./internal/doLimit'); var _doLimit2 = _interopRequireDefault(_doLimit); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time. * * @name eachSeries * @static * @memberOf module:Collections * @method * @see [async.each]{@link module:Collections.each} * @alias forEachSeries * @category Collection * @param {Array|Iterable|Object} coll - A collection to iterate over. * @param {AsyncFunction} iteratee - An async function to apply to each * item in `coll`. * The array index is not passed to the iteratee. * If you need the index, use `eachOfSeries`. * Invoked with (item, callback). * @param {Function} [callback] - A callback which is called when all * `iteratee` functions have finished, or an error occurs. Invoked with (err). */ exports.default = (0, _doLimit2.default)(_eachLimit2.default, 1); module.exports = exports['default']; },{"./eachLimit":63,"./internal/doLimit":66}],65:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // A temporary value used to identify if the loop should be broken. // See #1064, #1293 exports.default = {}; module.exports = exports["default"]; },{}],66:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = doLimit; function doLimit(fn, limit) { return function (iterable, iteratee, callback) { return fn(iterable, limit, iteratee, callback); }; } module.exports = exports["default"]; },{}],67:[function(_dereq_,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = _eachOfLimit; var _noop = _dereq_('lodash/noop'); var _noop2 = _interopRequireDefault(_noop); var _once = _dereq_('./once'); var _once2 = _interopRequireDefault(_once); var _iterator = _dereq_('./iterator'); var _iterator2 = _interopRequireDefault(_iterator); var _onlyOnce = _dereq_('./onlyOnce'); var _onlyOnce2 = _interopRequireDefault(_onlyOnce); var _breakLoop = _dereq_('./breakLoop'); var _breakLoop2 = _interopRequireDefault(_breakLoop); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _eachOfLimit(limit) { return function (obj, iteratee, callback) { callback = (0, _once2.default)(callback || _noop2.default); if (limit <= 0 || !obj) { return callback(null); } var nextElem = (0, _iterator2.default)(obj); var done = false; var running = 0; function iterateeCallback(err, value) { running -= 1; if (err) { done = true; callback(err); } else if (value === _breakLoop2.default || done && running <= 0) { done = true; return callback(null); } else { replenish(); } } function replenish() { while (running < limit && !done) { var elem = nextElem(); if (elem === null) { done = true; if (running <= 0) { callback(null); } return; } running += 1; iteratee(elem.value, elem.key, (0, _onlyOnce2.default)(iterateeCallback)); } } replenish(); }; } module.exports = exports['default']; },{"./breakLoop":65,"./iterator":70,"./once":71,"./onlyOnce":72,"lodash/noop":378}],68:[function(_dereq_,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (coll) { return iteratorSymbol && coll[iteratorSymbol] && coll[iteratorSymbol](); }; var iteratorSymbol = typeof Symbol === 'function' && Symbol.iterator; module.exports = exports['default']; },{}],69:[function(_dereq_,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (fn) { return function () /*...args, callback*/{ var args = (0, _slice2.default)(arguments); var callback = args.pop(); fn.call(this, args, callback); }; }; var _slice = _dereq_('./slice'); var _slice2 = _interopRequireDefault(_slice); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } module.exports = exports['default']; },{"./slice":74}],70:[function(_dereq_,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = iterator; var _isArrayLike = _dereq_('lodash/isArrayLike'); var _isArrayLike2 = _interopRequireDefault(_isArrayLike); var _getIterator = _dereq_('./getIterator'); var _getIterator2 = _interopRequireDefault(_getIterator); var _keys = _dereq_('lodash/keys'); var _keys2 = _interopRequireDefault(_keys); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function createArrayIterator(coll) { var i = -1; var len = coll.length; return function next() { return ++i < len ? { value: coll[i], key: i } : null; }; } function createES2015Iterator(iterator) { var i = -1; return function next() { var item = iterator.next(); if (item.done) return null; i++; return { value: item.value, key: i }; }; } function createObjectIterator(obj) { var okeys = (0, _keys2.default)(obj); var i = -1; var len = okeys.length; return function next() { var key = okeys[++i]; return i < len ? { value: obj[key], key: key } : null; }; } function iterator(coll) { if ((0, _isArrayLike2.default)(coll)) { return createArrayIterator(coll); } var iterator = (0, _getIterator2.default)(coll); return iterator ? createES2015Iterator(iterator) : createObjectIterator(coll); } module.exports = exports['default']; },{"./getIterator":68,"lodash/isArrayLike":370,"lodash/keys":377}],71:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = once; function once(fn) { return function () { if (fn === null) return; var callFn = fn; fn = null; callFn.apply(this, arguments); }; } module.exports = exports["default"]; },{}],72:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = onlyOnce; function onlyOnce(fn) { return function () { if (fn === null) throw new Error("Callback was already called."); var callFn = fn; fn = null; callFn.apply(this, arguments); }; } module.exports = exports["default"]; },{}],73:[function(_dereq_,module,exports){ (function (process){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.hasNextTick = exports.hasSetImmediate = undefined; exports.fallback = fallback; exports.wrap = wrap; var _slice = _dereq_('./slice'); var _slice2 = _interopRequireDefault(_slice); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var hasSetImmediate = exports.hasSetImmediate = typeof setImmediate === 'function' && setImmediate; var hasNextTick = exports.hasNextTick = typeof process === 'object' && typeof process.nextTick === 'function'; function fallback(fn) { setTimeout(fn, 0); } function wrap(defer) { return function (fn /*, ...args*/) { var args = (0, _slice2.default)(arguments, 1); defer(function () { fn.apply(null, args); }); }; } var _defer; if (hasSetImmediate) { _defer = setImmediate; } else if (hasNextTick) { _defer = process.nextTick; } else { _defer = fallback; } exports.default = wrap(_defer); }).call(this,_dereq_('_process')) },{"./slice":74,"_process":402}],74:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = slice; function slice(arrayLike, start) { start = start | 0; var newLen = Math.max(arrayLike.length - start, 0); var newArr = Array(newLen); for (var idx = 0; idx < newLen; idx++) { newArr[idx] = arrayLike[start + idx]; } return newArr; } module.exports = exports["default"]; },{}],75:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = _withoutIndex; function _withoutIndex(iteratee) { return function (value, index, callback) { return iteratee(value, callback); }; } module.exports = exports["default"]; },{}],76:[function(_dereq_,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.isAsync = undefined; var _asyncify = _dereq_('../asyncify'); var _asyncify2 = _interopRequireDefault(_asyncify); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var supportsSymbol = typeof Symbol === 'function'; function isAsync(fn) { return supportsSymbol && fn[Symbol.toStringTag] === 'AsyncFunction'; } function wrapAsync(asyncFn) { return isAsync(asyncFn) ? (0, _asyncify2.default)(asyncFn) : asyncFn; } exports.default = wrapAsync; exports.isAsync = isAsync; },{"../asyncify":62}],77:[function(_dereq_,module,exports){ (function (process,global){ /*! * async * https://github.com/caolan/async * * Copyright 2010-2014 Caolan McMahon * Released under the MIT license */ (function () { var async = {}; function noop() {} function identity(v) { return v; } function toBool(v) { return !!v; } function notId(v) { return !v; } // global on the server, window in the browser var previous_async; // Establish the root object, `window` (`self`) in the browser, `global` // on the server, or `this` in some virtual machines. We use `self` // instead of `window` for `WebWorker` support. var root = typeof self === 'object' && self.self === self && self || typeof global === 'object' && global.global === global && global || this; if (root != null) { previous_async = root.async; } async.noConflict = function () { root.async = previous_async; return async; }; function only_once(fn) { return function() { if (fn === null) throw new Error("Callback was already called."); fn.apply(this, arguments); fn = null; }; } function _once(fn) { return function() { if (fn === null) return; fn.apply(this, arguments); fn = null; }; } //// cross-browser compatiblity functions //// var _toString = Object.prototype.toString; var _isArray = Array.isArray || function (obj) { return _toString.call(obj) === '[object Array]'; }; // Ported from underscore.js isObject var _isObject = function(obj) { var type = typeof obj; return type === 'function' || type === 'object' && !!obj; }; function _isArrayLike(arr) { return _isArray(arr) || ( // has a positive integer length property typeof arr.length === "number" && arr.length >= 0 && arr.length % 1 === 0 ); } function _arrayEach(arr, iterator) { var index = -1, length = arr.length; while (++index < length) { iterator(arr[index], index, arr); } } function _map(arr, iterator) { var index = -1, length = arr.length, result = Array(length); while (++index < length) { result[index] = iterator(arr[index], index, arr); } return result; } function _range(count) { return _map(Array(count), function (v, i) { return i; }); } function _reduce(arr, iterator, memo) { _arrayEach(arr, function (x, i, a) { memo = iterator(memo, x, i, a); }); return memo; } function _forEachOf(object, iterator) { _arrayEach(_keys(object), function (key) { iterator(object[key], key); }); } function _indexOf(arr, item) { for (var i = 0; i < arr.length; i++) { if (arr[i] === item) return i; } return -1; } var _keys = Object.keys || function (obj) { var keys = []; for (var k in obj) { if (obj.hasOwnProperty(k)) { keys.push(k); } } return keys; }; function _keyIterator(coll) { var i = -1; var len; var keys; if (_isArrayLike(coll)) { len = coll.length; return function next() { i++; return i < len ? i : null; }; } else { keys = _keys(coll); len = keys.length; return function next() { i++; return i < len ? keys[i] : null; }; } } // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html) // This accumulates the arguments passed into an array, after a given index. // From underscore.js (https://github.com/jashkenas/underscore/pull/2140). function _restParam(func, startIndex) { startIndex = startIndex == null ? func.length - 1 : +startIndex; return function() { var length = Math.max(arguments.length - startIndex, 0); var rest = Array(length); for (var index = 0; index < length; index++) { rest[index] = arguments[index + startIndex]; } switch (startIndex) { case 0: return func.call(this, rest); case 1: return func.call(this, arguments[0], rest); } // Currently unused but handle cases outside of the switch statement: // var args = Array(startIndex + 1); // for (index = 0; index < startIndex; index++) { // args[index] = arguments[index]; // } // args[startIndex] = rest; // return func.apply(this, args); }; } function _withoutIndex(iterator) { return function (value, index, callback) { return iterator(value, callback); }; } //// exported async module functions //// //// nextTick implementation with browser-compatible fallback //// // capture the global reference to guard against fakeTimer mocks var _setImmediate = typeof setImmediate === 'function' && setImmediate; var _delay = _setImmediate ? function(fn) { // not a direct alias for IE10 compatibility _setImmediate(fn); } : function(fn) { setTimeout(fn, 0); }; if (typeof process === 'object' && typeof process.nextTick === 'function') { async.nextTick = process.nextTick; } else { async.nextTick = _delay; } async.setImmediate = _setImmediate ? _delay : async.nextTick; async.forEach = async.each = function (arr, iterator, callback) { return async.eachOf(arr, _withoutIndex(iterator), callback); }; async.forEachSeries = async.eachSeries = function (arr, iterator, callback) { return async.eachOfSeries(arr, _withoutIndex(iterator), callback); }; async.forEachLimit = async.eachLimit = function (arr, limit, iterator, callback) { return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback); }; async.forEachOf = async.eachOf = function (object, iterator, callback) { callback = _once(callback || noop); object = object || []; var iter = _keyIterator(object); var key, completed = 0; while ((key = iter()) != null) { completed += 1; iterator(object[key], key, only_once(done)); } if (completed === 0) callback(null); function done(err) { completed--; if (err) { callback(err); } // Check key is null in case iterator isn't exhausted // and done resolved synchronously. else if (key === null && completed <= 0) { callback(null); } } }; async.forEachOfSeries = async.eachOfSeries = function (obj, iterator, callback) { callback = _once(callback || noop); obj = obj || []; var nextKey = _keyIterator(obj); var key = nextKey(); function iterate() { var sync = true; if (key === null) { return callback(null); } iterator(obj[key], key, only_once(function (err) { if (err) { callback(err); } else { key = nextKey(); if (key === null) { return callback(null); } else { if (sync) { async.setImmediate(iterate); } else { iterate(); } } } })); sync = false; } iterate(); }; async.forEachOfLimit = async.eachOfLimit = function (obj, limit, iterator, callback) { _eachOfLimit(limit)(obj, iterator, callback); }; function _eachOfLimit(limit) { return function (obj, iterator, callback) { callback = _once(callback || noop); obj = obj || []; var nextKey = _keyIterator(obj); if (limit <= 0) { return callback(null); } var done = false; var running = 0; var errored = false; (function replenish () { if (done && running <= 0) { return callback(null); } while (running < limit && !errored) { var key = nextKey(); if (key === null) { done = true; if (running <= 0) { callback(null); } return; } running += 1; iterator(obj[key], key, only_once(function (err) { running -= 1; if (err) { callback(err); errored = true; } else { replenish(); } })); } })(); }; } function doParallel(fn) { return function (obj, iterator, callback) { return fn(async.eachOf, obj, iterator, callback); }; } function doParallelLimit(fn) { return function (obj, limit, iterator, callback) { return fn(_eachOfLimit(limit), obj, iterator, callback); }; } function doSeries(fn) { return function (obj, iterator, callback) { return fn(async.eachOfSeries, obj, iterator, callback); }; } function _asyncMap(eachfn, arr, iterator, callback) { callback = _once(callback || noop); arr = arr || []; var results = _isArrayLike(arr) ? [] : {}; eachfn(arr, function (value, index, callback) { iterator(value, function (err, v) { results[index] = v; callback(err); }); }, function (err) { callback(err, results); }); } async.map = doParallel(_asyncMap); async.mapSeries = doSeries(_asyncMap); async.mapLimit = doParallelLimit(_asyncMap); // reduce only has a series version, as doing reduce in parallel won't // work in many situations. async.inject = async.foldl = async.reduce = function (arr, memo, iterator, callback) { async.eachOfSeries(arr, function (x, i, callback) { iterator(memo, x, function (err, v) { memo = v; callback(err); }); }, function (err) { callback(err, memo); }); }; async.foldr = async.reduceRight = function (arr, memo, iterator, callback) { var reversed = _map(arr, identity).reverse(); async.reduce(reversed, memo, iterator, callback); }; async.transform = function (arr, memo, iterator, callback) { if (arguments.length === 3) { callback = iterator; iterator = memo; memo = _isArray(arr) ? [] : {}; } async.eachOf(arr, function(v, k, cb) { iterator(memo, v, k, cb); }, function(err) { callback(err, memo); }); }; function _filter(eachfn, arr, iterator, callback) { var results = []; eachfn(arr, function (x, index, callback) { iterator(x, function (v) { if (v) { results.push({index: index, value: x}); } callback(); }); }, function () { callback(_map(results.sort(function (a, b) { return a.index - b.index; }), function (x) { return x.value; })); }); } async.select = async.filter = doParallel(_filter); async.selectLimit = async.filterLimit = doParallelLimit(_filter); async.selectSeries = async.filterSeries = doSeries(_filter); function _reject(eachfn, arr, iterator, callback) { _filter(eachfn, arr, function(value, cb) { iterator(value, function(v) { cb(!v); }); }, callback); } async.reject = doParallel(_reject); async.rejectLimit = doParallelLimit(_reject); async.rejectSeries = doSeries(_reject); function _createTester(eachfn, check, getResult) { return function(arr, limit, iterator, cb) { function done() { if (cb) cb(getResult(false, void 0)); } function iteratee(x, _, callback) { if (!cb) return callback(); iterator(x, function (v) { if (cb && check(v)) { cb(getResult(true, x)); cb = iterator = false; } callback(); }); } if (arguments.length > 3) { eachfn(arr, limit, iteratee, done); } else { cb = iterator; iterator = limit; eachfn(arr, iteratee, done); } }; } async.any = async.some = _createTester(async.eachOf, toBool, identity); async.someLimit = _createTester(async.eachOfLimit, toBool, identity); async.all = async.every = _createTester(async.eachOf, notId, notId); async.everyLimit = _createTester(async.eachOfLimit, notId, notId); function _findGetResult(v, x) { return x; } async.detect = _createTester(async.eachOf, identity, _findGetResult); async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult); async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult); async.sortBy = function (arr, iterator, callback) { async.map(arr, function (x, callback) { iterator(x, function (err, criteria) { if (err) { callback(err); } else { callback(null, {value: x, criteria: criteria}); } }); }, function (err, results) { if (err) { return callback(err); } else { callback(null, _map(results.sort(comparator), function (x) { return x.value; })); } }); function comparator(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; } }; async.auto = function (tasks, concurrency, callback) { if (typeof arguments[1] === 'function') { // concurrency is optional, shift the args. callback = concurrency; concurrency = null; } callback = _once(callback || noop); var keys = _keys(tasks); var remainingTasks = keys.length; if (!remainingTasks) { return callback(null); } if (!concurrency) { concurrency = remainingTasks; } var results = {}; var runningTasks = 0; var hasError = false; var listeners = []; function addListener(fn) { listeners.unshift(fn); } function removeListener(fn) { var idx = _indexOf(listeners, fn); if (idx >= 0) listeners.splice(idx, 1); } function taskComplete() { remainingTasks--; _arrayEach(listeners.slice(0), function (fn) { fn(); }); } addListener(function () { if (!remainingTasks) { callback(null, results); } }); _arrayEach(keys, function (k) { if (hasError) return; var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; var taskCallback = _restParam(function(err, args) { runningTasks--; if (args.length <= 1) { args = args[0]; } if (err) { var safeResults = {}; _forEachOf(results, function(val, rkey) { safeResults[rkey] = val; }); safeResults[k] = args; hasError = true; callback(err, safeResults); } else { results[k] = args; async.setImmediate(taskComplete); } }); var requires = task.slice(0, task.length - 1); // prevent dead-locks var len = requires.length; var dep; while (len--) { if (!(dep = tasks[requires[len]])) { throw new Error('Has nonexistent dependency in ' + requires.join(', ')); } if (_isArray(dep) && _indexOf(dep, k) >= 0) { throw new Error('Has cyclic dependencies'); } } function ready() { return runningTasks < concurrency && _reduce(requires, function (a, x) { return (a && results.hasOwnProperty(x)); }, true) && !results.hasOwnProperty(k); } if (ready()) { runningTasks++; task[task.length - 1](taskCallback, results); } else { addListener(listener); } function listener() { if (ready()) { runningTasks++; removeListener(listener); task[task.length - 1](taskCallback, results); } } }); }; async.retry = function(times, task, callback) { var DEFAULT_TIMES = 5; var DEFAULT_INTERVAL = 0; var attempts = []; var opts = { times: DEFAULT_TIMES, interval: DEFAULT_INTERVAL }; function parseTimes(acc, t){ if(typeof t === 'number'){ acc.times = parseInt(t, 10) || DEFAULT_TIMES; } else if(typeof t === 'object'){ acc.times = parseInt(t.times, 10) || DEFAULT_TIMES; acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL; } else { throw new Error('Unsupported argument type for \'times\': ' + typeof t); } } var length = arguments.length; if (length < 1 || length > 3) { throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)'); } else if (length <= 2 && typeof times === 'function') { callback = task; task = times; } if (typeof times !== 'function') { parseTimes(opts, times); } opts.callback = callback; opts.task = task; function wrappedTask(wrappedCallback, wrappedResults) { function retryAttempt(task, finalAttempt) { return function(seriesCallback) { task(function(err, result){ seriesCallback(!err || finalAttempt, {err: err, result: result}); }, wrappedResults); }; } function retryInterval(interval){ return function(seriesCallback){ setTimeout(function(){ seriesCallback(null); }, interval); }; } while (opts.times) { var finalAttempt = !(opts.times-=1); attempts.push(retryAttempt(opts.task, finalAttempt)); if(!finalAttempt && opts.interval > 0){ attempts.push(retryInterval(opts.interval)); } } async.series(attempts, function(done, data){ data = data[data.length - 1]; (wrappedCallback || opts.callback)(data.err, data.result); }); } // If a callback is passed, run this as a controll flow return opts.callback ? wrappedTask() : wrappedTask; }; async.waterfall = function (tasks, callback) { callback = _once(callback || noop); if (!_isArray(tasks)) { var err = new Error('First argument to waterfall must be an array of functions'); return callback(err); } if (!tasks.length) { return callback(); } function wrapIterator(iterator) { return _restParam(function (err, args) { if (err) { callback.apply(null, [err].concat(args)); } else { var next = iterator.next(); if (next) { args.push(wrapIterator(next)); } else { args.push(callback); } ensureAsync(iterator).apply(null, args); } }); } wrapIterator(async.iterator(tasks))(); }; function _parallel(eachfn, tasks, callback) { callback = callback || noop; var results = _isArrayLike(tasks) ? [] : {}; eachfn(tasks, function (task, key, callback) { task(_restParam(function (err, args) { if (args.length <= 1) { args = args[0]; } results[key] = args; callback(err); })); }, function (err) { callback(err, results); }); } async.parallel = function (tasks, callback) { _parallel(async.eachOf, tasks, callback); }; async.parallelLimit = function(tasks, limit, callback) { _parallel(_eachOfLimit(limit), tasks, callback); }; async.series = function(tasks, callback) { _parallel(async.eachOfSeries, tasks, callback); }; async.iterator = function (tasks) { function makeCallback(index) { function fn() { if (tasks.length) { tasks[index].apply(null, arguments); } return fn.next(); } fn.next = function () { return (index < tasks.length - 1) ? makeCallback(index + 1): null; }; return fn; } return makeCallback(0); }; async.apply = _restParam(function (fn, args) { return _restParam(function (callArgs) { return fn.apply( null, args.concat(callArgs) ); }); }); function _concat(eachfn, arr, fn, callback) { var result = []; eachfn(arr, function (x, index, cb) { fn(x, function (err, y) { result = result.concat(y || []); cb(err); }); }, function (err) { callback(err, result); }); } async.concat = doParallel(_concat); async.concatSeries = doSeries(_concat); async.whilst = function (test, iterator, callback) { callback = callback || noop; if (test()) { var next = _restParam(function(err, args) { if (err) { callback(err); } else if (test.apply(this, args)) { iterator(next); } else { callback.apply(null, [null].concat(args)); } }); iterator(next); } else { callback(null); } }; async.doWhilst = function (iterator, test, callback) { var calls = 0; return async.whilst(function() { return ++calls <= 1 || test.apply(this, arguments); }, iterator, callback); }; async.until = function (test, iterator, callback) { return async.whilst(function() { return !test.apply(this, arguments); }, iterator, callback); }; async.doUntil = function (iterator, test, callback) { return async.doWhilst(iterator, function() { return !test.apply(this, arguments); }, callback); }; async.during = function (test, iterator, callback) { callback = callback || noop; var next = _restParam(function(err, args) { if (err) { callback(err); } else { args.push(check); test.apply(this, args); } }); var check = function(err, truth) { if (err) { callback(err); } else if (truth) { iterator(next); } else { callback(null); } }; test(check); }; async.doDuring = function (iterator, test, callback) { var calls = 0; async.during(function(next) { if (calls++ < 1) { next(null, true); } else { test.apply(this, arguments); } }, iterator, callback); }; function _queue(worker, concurrency, payload) { if (concurrency == null) { concurrency = 1; } else if(concurrency === 0) { throw new Error('Concurrency must not be zero'); } function _insert(q, data, pos, callback) { if (callback != null && typeof callback !== "function") { throw new Error("task callback must be a function"); } q.started = true; if (!_isArray(data)) { data = [data]; } if(data.length === 0 && q.idle()) { // call drain immediately if there are no tasks return async.setImmediate(function() { q.drain(); }); } _arrayEach(data, function(task) { var item = { data: task, callback: callback || noop }; if (pos) { q.tasks.unshift(item); } else { q.tasks.push(item); } if (q.tasks.length === q.concurrency) { q.saturated(); } }); async.setImmediate(q.process); } function _next(q, tasks) { return function(){ workers -= 1; var removed = false; var args = arguments; _arrayEach(tasks, function (task) { _arrayEach(workersList, function (worker, index) { if (worker === task && !removed) { workersList.splice(index, 1); removed = true; } }); task.callback.apply(task, args); }); if (q.tasks.length + workers === 0) { q.drain(); } q.process(); }; } var workers = 0; var workersList = []; var q = { tasks: [], concurrency: concurrency, payload: payload, saturated: noop, empty: noop, drain: noop, started: false, paused: false, push: function (data, callback) { _insert(q, data, false, callback); }, kill: function () { q.drain = noop; q.tasks = []; }, unshift: function (data, callback) { _insert(q, data, true, callback); }, process: function () { while(!q.paused && workers < q.concurrency && q.tasks.length){ var tasks = q.payload ? q.tasks.splice(0, q.payload) : q.tasks.splice(0, q.tasks.length); var data = _map(tasks, function (task) { return task.data; }); if (q.tasks.length === 0) { q.empty(); } workers += 1; workersList.push(tasks[0]); var cb = only_once(_next(q, tasks)); worker(data, cb); } }, length: function () { return q.tasks.length; }, running: function () { return workers; }, workersList: function () { return workersList; }, idle: function() { return q.tasks.length + workers === 0; }, pause: function () { q.paused = true; }, resume: function () { if (q.paused === false) { return; } q.paused = false; var resumeCount = Math.min(q.concurrency, q.tasks.length); // Need to call q.process once per concurrent // worker to preserve full concurrency after pause for (var w = 1; w <= resumeCount; w++) { async.setImmediate(q.process); } } }; return q; } async.queue = function (worker, concurrency) { var q = _queue(function (items, cb) { worker(items[0], cb); }, concurrency, 1); return q; }; async.priorityQueue = function (worker, concurrency) { function _compareTasks(a, b){ return a.priority - b.priority; } function _binarySearch(sequence, item, compare) { var beg = -1, end = sequence.length - 1; while (beg < end) { var mid = beg + ((end - beg + 1) >>> 1); if (compare(item, sequence[mid]) >= 0) { beg = mid; } else { end = mid - 1; } } return beg; } function _insert(q, data, priority, callback) { if (callback != null && typeof callback !== "function") { throw new Error("task callback must be a function"); } q.started = true; if (!_isArray(data)) { data = [data]; } if(data.length === 0) { // call drain immediately if there are no tasks return async.setImmediate(function() { q.drain(); }); } _arrayEach(data, function(task) { var item = { data: task, priority: priority, callback: typeof callback === 'function' ? callback : noop }; q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item); if (q.tasks.length === q.concurrency) { q.saturated(); } async.setImmediate(q.process); }); } // Start with a normal queue var q = async.queue(worker, concurrency); // Override push to accept second parameter representing priority q.push = function (data, priority, callback) { _insert(q, data, priority, callback); }; // Remove unshift function delete q.unshift; return q; }; async.cargo = function (worker, payload) { return _queue(worker, 1, payload); }; function _console_fn(name) { return _restParam(function (fn, args) { fn.apply(null, args.concat([_restParam(function (err, args) { if (typeof console === 'object') { if (err) { if (console.error) { console.error(err); } } else if (console[name]) { _arrayEach(args, function (x) { console[name](x); }); } } })])); }); } async.log = _console_fn('log'); async.dir = _console_fn('dir'); /*async.info = _console_fn('info'); async.warn = _console_fn('warn'); async.error = _console_fn('error');*/ async.memoize = function (fn, hasher) { var memo = {}; var queues = {}; var has = Object.prototype.hasOwnProperty; hasher = hasher || identity; var memoized = _restParam(function memoized(args) { var callback = args.pop(); var key = hasher.apply(null, args); if (has.call(memo, key)) { async.setImmediate(function () { callback.apply(null, memo[key]); }); } else if (has.call(queues, key)) { queues[key].push(callback); } else { queues[key] = [callback]; fn.apply(null, args.concat([_restParam(function (args) { memo[key] = args; var q = queues[key]; delete queues[key]; for (var i = 0, l = q.length; i < l; i++) { q[i].apply(null, args); } })])); } }); memoized.memo = memo; memoized.unmemoized = fn; return memoized; }; async.unmemoize = function (fn) { return function () { return (fn.unmemoized || fn).apply(null, arguments); }; }; function _times(mapper) { return function (count, iterator, callback) { mapper(_range(count), iterator, callback); }; } async.times = _times(async.map); async.timesSeries = _times(async.mapSeries); async.timesLimit = function (count, limit, iterator, callback) { return async.mapLimit(_range(count), limit, iterator, callback); }; async.seq = function (/* functions... */) { var fns = arguments; return _restParam(function (args) { var that = this; var callback = args[args.length - 1]; if (typeof callback == 'function') { args.pop(); } else { callback = noop; } async.reduce(fns, args, function (newargs, fn, cb) { fn.apply(that, newargs.concat([_restParam(function (err, nextargs) { cb(err, nextargs); })])); }, function (err, results) { callback.apply(that, [err].concat(results)); }); }); }; async.compose = function (/* functions... */) { return async.seq.apply(null, Array.prototype.reverse.call(arguments)); }; function _applyEach(eachfn) { return _restParam(function(fns, args) { var go = _restParam(function(args) { var that = this; var callback = args.pop(); return eachfn(fns, function (fn, _, cb) { fn.apply(that, args.concat([cb])); }, callback); }); if (args.length) { return go.apply(this, args); } else { return go; } }); } async.applyEach = _applyEach(async.eachOf); async.applyEachSeries = _applyEach(async.eachOfSeries); async.forever = function (fn, callback) { var done = only_once(callback || noop); var task = ensureAsync(fn); function next(err) { if (err) { return done(err); } task(next); } next(); }; function ensureAsync(fn) { return _restParam(function (args) { var callback = args.pop(); args.push(function () { var innerArgs = arguments; if (sync) { async.setImmediate(function () { callback.apply(null, innerArgs); }); } else { callback.apply(null, innerArgs); } }); var sync = true; fn.apply(this, args); sync = false; }); } async.ensureAsync = ensureAsync; async.constant = _restParam(function(values) { var args = [null].concat(values); return function (callback) { return callback.apply(this, args); }; }); async.wrapSync = async.asyncify = function asyncify(func) { return _restParam(function (args) { var callback = args.pop(); var result; try { result = func.apply(this, args); } catch (e) { return callback(e); } // if result is Promise object if (_isObject(result) && typeof result.then === "function") { result.then(function(value) { callback(null, value); })["catch"](function(err) { callback(err.message ? err : new Error(err)); }); } else { callback(null, result); } }); }; // Node.js if (typeof module === 'object' && module.exports) { module.exports = async; } // AMD / RequireJS else if (typeof define === 'function' && define.amd) { define([], function () { return async; }); } // included directly via