├── .gitattributes ├── .github └── workflows │ ├── build-android.yml │ ├── build-ios.yml │ ├── notice-yarn-changes.yml │ ├── validate-android.yml │ ├── validate-cpp.yml │ └── validate-js.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── android ├── CMakeLists.txt ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src │ └── main │ ├── AndroidManifest.xml │ ├── cpp │ └── cpp-adapter.cpp │ └── java │ └── com │ └── margelo │ └── bignumber │ ├── BigNumberModule.java │ └── BigNumberPackage.java ├── cpp ├── BigNumber │ ├── MGBigNumber.cpp │ ├── MGBigNumber.h │ ├── MGModContext.cpp │ ├── MGModContext.h │ ├── MGRedBigNum.cpp │ └── MGRedBigNum.h ├── JSI Utils │ ├── MGJSIMacros.h │ ├── MGSmartHostObject.cpp │ ├── MGSmartHostObject.h │ ├── MGThreadAwareHostObject.cpp │ ├── MGThreadAwareHostObject.h │ ├── TypedArray.cpp │ └── TypedArray.h ├── MGBigNumberHostObject.cpp ├── MGBigNumberHostObject.h └── Utils │ ├── MGBigNumHelper.cpp │ ├── MGBigNumHelper.h │ ├── MGDispatchQueue.cpp │ └── MGDispatchQueue.h ├── example ├── .bundle │ └── config ├── .gitignore ├── .watchmanconfig ├── Gemfile ├── Gemfile.lock ├── __tests__ │ └── App-test.tsx ├── _node-version ├── android │ ├── app │ │ ├── build.gradle │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── bignumberexample │ │ │ │ └── ReactNativeFlipper.java │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── bignumberexample │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── release │ │ │ └── java │ │ │ └── com │ │ │ └── bignumberexample │ │ │ └── ReactNativeFlipper.java │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── index.js ├── ios │ ├── .xcode.env │ ├── BigNumberExample.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── BigNumberExample.xcscheme │ ├── BigNumberExample.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── BigNumberExample │ │ ├── AppDelegate.h │ │ ├── AppDelegate.mm │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ └── main.m │ ├── BigNumberExampleTests │ │ ├── BigNumberExampleTests.m │ │ └── Info.plist │ ├── Podfile │ ├── Podfile.lock │ └── _xcode.env ├── metro.config.js ├── package.json ├── patches │ └── elliptic+6.5.4.patch ├── src │ ├── App.tsx │ ├── Testing │ │ ├── MochaRNAdapter.ts │ │ ├── MochaSetup.ts │ │ ├── TestList.ts │ │ ├── bn-tests │ │ │ ├── README.md │ │ │ ├── arithmetic-test.js │ │ │ ├── binary-test.js │ │ │ ├── constructor-test.js │ │ │ ├── fixtures.js │ │ │ ├── pummel │ │ │ │ └── dh-group-test.js │ │ │ ├── res-test.js │ │ │ └── utils-test.js │ │ └── elliptic-tests │ │ │ └── curves.ts │ ├── bn-elliptic │ │ ├── lib │ │ │ ├── elliptic │ │ │ │ ├── curve │ │ │ │ │ ├── base.js │ │ │ │ │ ├── edwards.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── mont.js │ │ │ │ │ └── short.js │ │ │ │ ├── curves.js │ │ │ │ ├── ec │ │ │ │ │ ├── index.js │ │ │ │ │ ├── key.js │ │ │ │ │ └── signature.js │ │ │ │ ├── eddsa │ │ │ │ │ ├── index.js │ │ │ │ │ ├── key.js │ │ │ │ │ └── signature.js │ │ │ │ ├── precomputed │ │ │ │ │ └── secp256k1.js │ │ │ │ └── utils.js │ │ │ └── index.js │ │ └── package.json │ ├── components │ │ ├── Button.tsx │ │ ├── CorrectResultItem.tsx │ │ ├── IncorrectResultItem.tsx │ │ ├── Indentator.tsx │ │ ├── Suite.tsx │ │ └── TestItem.tsx │ └── navigators │ │ ├── Root.tsx │ │ ├── RootProps.ts │ │ └── children │ │ ├── Entry │ │ ├── Entry.tsx │ │ ├── EntryProps.ts │ │ └── TestItemType.ts │ │ ├── TestingScreen │ │ ├── RowItemType.ts │ │ ├── TestingScreen.tsx │ │ └── TestingScreenProps.ts │ │ └── benchmarks │ │ ├── Benchmarks.tsx │ │ └── BenchmarksProps.ts ├── tsconfig.json └── yarn.lock ├── img ├── banner-dark.png ├── banner-light.png ├── exodus.svg ├── expo.png └── react-native.png ├── ios ├── BigNumber.xcodeproj │ └── project.pbxproj ├── BigNumberModule.h └── BigNumberModule.mm ├── package.json ├── react-native-bignumber.podspec ├── src ├── BigNumber.ts ├── NativeBigNumber │ └── NativeBigNumber.ts └── index.ts ├── tsconfig.json └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/build-android.yml: -------------------------------------------------------------------------------- 1 | name: Build Android 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - '.github/workflows/build-android.yml' 9 | - 'android/**' 10 | - 'example/android/**' 11 | - 'yarn.lock' 12 | - 'example/yarn.lock' 13 | pull_request: 14 | paths: 15 | - '.github/workflows/build-android.yml' 16 | - 'android/**' 17 | - 'example/android/**' 18 | - 'yarn.lock' 19 | - 'example/yarn.lock' 20 | 21 | jobs: 22 | build_example: 23 | name: Build Android Example App 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: actions/checkout@v2 27 | 28 | - name: Setup JDK 11 29 | uses: actions/setup-java@v1 30 | with: 31 | java-version: 11 32 | 33 | - name: Get yarn cache directory path 34 | id: yarn-cache-dir-path 35 | run: echo "::set-output name=dir::$(yarn cache dir)" 36 | - name: Restore node_modules from cache 37 | uses: actions/cache@v2 38 | id: yarn-cache 39 | with: 40 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 41 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 42 | restore-keys: | 43 | ${{ runner.os }}-yarn- 44 | - name: Install node_modules 45 | run: yarn install --frozen-lockfile 46 | - name: Install node_modules for example/ 47 | run: yarn install --frozen-lockfile --cwd example 48 | 49 | - name: Restore Gradle cache 50 | uses: actions/cache@v2 51 | with: 52 | path: | 53 | ~/.gradle/caches 54 | ~/.gradle/wrapper 55 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} 56 | restore-keys: | 57 | ${{ runner.os }}-gradle- 58 | - name: Run Gradle Build for android/ 59 | run: cd android && ./gradlew assembleDebug --build-cache && cd .. 60 | - name: Run Gradle Build for example/android/ 61 | run: cd example/android && ./gradlew assembleDebug --build-cache && cd ../.. 62 | -------------------------------------------------------------------------------- /.github/workflows/build-ios.yml: -------------------------------------------------------------------------------- 1 | name: Build iOS 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - '.github/workflows/build-ios.yml' 9 | - 'ios/**' 10 | - '*.podspec' 11 | - 'example/ios/**' 12 | pull_request: 13 | paths: 14 | - '.github/workflows/build-ios.yml' 15 | - 'ios/**' 16 | - '*.podspec' 17 | - 'example/ios/**' 18 | 19 | jobs: 20 | build: 21 | name: Build iOS Example App 22 | runs-on: macOS-latest 23 | defaults: 24 | run: 25 | working-directory: example/ios 26 | steps: 27 | - uses: actions/checkout@v2 28 | 29 | - name: Get yarn cache directory path 30 | id: yarn-cache-dir-path 31 | run: echo "::set-output name=dir::$(yarn cache dir)" 32 | - name: Restore node_modules from cache 33 | uses: actions/cache@v2 34 | id: yarn-cache 35 | with: 36 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 37 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 38 | restore-keys: | 39 | ${{ runner.os }}-yarn- 40 | - name: Install node_modules for example/ 41 | run: yarn install --frozen-lockfile --cwd .. 42 | 43 | - name: Restore buildcache 44 | uses: mikehardy/buildcache-action@v1 45 | continue-on-error: true 46 | 47 | - name: Setup Ruby (bundle) 48 | uses: ruby/setup-ruby@v1 49 | with: 50 | ruby-version: 2.6 51 | bundler-cache: true 52 | working-directory: example/ios 53 | 54 | - name: Restore Pods cache 55 | uses: actions/cache@v2 56 | with: 57 | path: | 58 | example/ios/Pods 59 | ~/Library/Caches/CocoaPods 60 | ~/.cocoapods 61 | key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} 62 | restore-keys: | 63 | ${{ runner.os }}-pods- 64 | - name: Install Pods 65 | run: bundle exec pod check || bundle exec pod install 66 | - name: Install xcpretty 67 | run: gem install xcpretty 68 | - name: Build App 69 | run: "set -o pipefail && xcodebuild \ 70 | CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ \ 71 | -derivedDataPath build -UseModernBuildSystem=YES \ 72 | -workspace BigNumberExample.xcworkspace \ 73 | -scheme BigNumberExample \ 74 | -sdk iphonesimulator \ 75 | -configuration Debug \ 76 | -destination 'platform=iOS Simulator,name=iPhone 11 Pro' \ 77 | build \ 78 | CODE_SIGNING_ALLOWED=NO | xcpretty" 79 | -------------------------------------------------------------------------------- /.github/workflows/notice-yarn-changes.yml: -------------------------------------------------------------------------------- 1 | name: Notice yarn.lock changes 2 | on: [pull_request] 3 | 4 | jobs: 5 | check: 6 | runs-on: ubuntu-latest 7 | permissions: 8 | pull-requests: write 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v2 12 | - name: Notice yarn.lock changes 13 | uses: Simek/yarn-lock-changes@main 14 | with: 15 | token: ${{ secrets.GITHUB_TOKEN }} 16 | collapsibleThreshold: '25' 17 | failOnDowngrade: 'false' 18 | path: 'yarn.lock' 19 | updateComment: 'true' 20 | -------------------------------------------------------------------------------- /.github/workflows/validate-android.yml: -------------------------------------------------------------------------------- 1 | name: Validate Android 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - '.github/workflows/validate-android.yml' 9 | - 'android/**' 10 | - '.editorconfig' 11 | pull_request: 12 | paths: 13 | - '.github/workflows/validate-android.yml' 14 | - 'android/**' 15 | - '.editorconfig' 16 | 17 | jobs: 18 | lint: 19 | name: Gradle Lint 20 | runs-on: ubuntu-latest 21 | defaults: 22 | run: 23 | working-directory: ./android 24 | steps: 25 | - uses: actions/checkout@v2 26 | - name: Setup JDK 11 27 | uses: actions/setup-java@v1 28 | with: 29 | java-version: 11 30 | 31 | - name: Get yarn cache directory path 32 | id: yarn-cache-dir-path 33 | run: echo "::set-output name=dir::$(yarn cache dir)" 34 | - name: Restore node_modules from cache 35 | uses: actions/cache@v2 36 | id: yarn-cache 37 | with: 38 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 39 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 40 | restore-keys: | 41 | ${{ runner.os }}-yarn- 42 | - name: Install node_modules 43 | run: yarn install --frozen-lockfile --cwd .. 44 | - name: Install node_modules for example/ 45 | run: yarn install --frozen-lockfile --cwd ../example 46 | 47 | - name: Restore Gradle cache 48 | uses: actions/cache@v2 49 | with: 50 | path: | 51 | ~/.gradle/caches 52 | ~/.gradle/wrapper 53 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} 54 | restore-keys: | 55 | ${{ runner.os }}-gradle- 56 | - name: Run Gradle Lint 57 | run: ./gradlew lint --build-cache 58 | - name: Verify lint report exists 59 | run: | 60 | ls -R build/reports 61 | if [ ! -f "build/reports/lint-results-debug.xml" ]; then 62 | echo "Lint report not found!" 63 | exit 1 64 | fi 65 | - name: Parse Gradle Lint Report 66 | uses: yutailang0119/action-android-lint@v1.0.2 67 | with: 68 | xml_path: android/build/reports/lint-results-debug.xml 69 | # ktlint: 70 | # name: Kotlin Lint 71 | # runs-on: ubuntu-latest 72 | # steps: 73 | # - uses: actions/checkout@v2 74 | # - name: Run KTLint 75 | # uses: mrousavy/action-ktlint@v1.7 76 | # with: 77 | # github_token: ${{ secrets.github_token }} 78 | -------------------------------------------------------------------------------- /.github/workflows/validate-cpp.yml: -------------------------------------------------------------------------------- 1 | name: Validate C++ 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - '.github/workflows/validate-cpp.yml' 9 | - 'cpp/**' 10 | - 'android/src/main/cpp/**' 11 | pull_request: 12 | paths: 13 | - '.github/workflows/validate-cpp.yml' 14 | - 'cpp/**' 15 | - 'android/src/main/cpp/**' 16 | 17 | jobs: 18 | lint: 19 | name: cpplint 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v2 23 | - uses: reviewdog/action-cpplint@master 24 | with: 25 | github_token: ${{ secrets.github_token }} 26 | reporter: github-pr-review 27 | flags: --linelength=230 28 | targets: --recursive cpp android/src/main/cpp 29 | filter: "-legal/copyright\ 30 | ,-readability/todo\ 31 | ,-build/namespaces\ 32 | ,-whitespace/comments\ 33 | ,-build/include_order\ 34 | " 35 | -------------------------------------------------------------------------------- /.github/workflows/validate-js.yml: -------------------------------------------------------------------------------- 1 | name: Validate JS 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - '.github/workflows/validate-js.yml' 9 | - 'src/**' 10 | - '*.json' 11 | - '*.js' 12 | - '*.lock' 13 | - 'example/src/**' 14 | - 'example/*.json' 15 | - 'example/*.js' 16 | - 'example/*.lock' 17 | - 'example/*.tsx' 18 | pull_request: 19 | paths: 20 | - '.github/workflows/validate-js.yml' 21 | - 'src/**' 22 | - '*.json' 23 | - '*.js' 24 | - '*.lock' 25 | - 'example/src/**' 26 | - 'example/*.json' 27 | - 'example/*.js' 28 | - 'example/*.lock' 29 | - 'example/*.tsx' 30 | 31 | jobs: 32 | compile: 33 | name: Compile JS (tsc) 34 | runs-on: ubuntu-latest 35 | steps: 36 | - uses: actions/checkout@v2 37 | 38 | - name: Install reviewdog 39 | uses: reviewdog/action-setup@v1 40 | 41 | - name: Get yarn cache directory path 42 | id: yarn-cache-dir-path 43 | run: echo "::set-output name=dir::$(yarn cache dir)" 44 | - name: Restore node_modules from cache 45 | uses: actions/cache@v2 46 | id: yarn-cache 47 | with: 48 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 49 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 50 | restore-keys: | 51 | ${{ runner.os }}-yarn- 52 | 53 | - name: Install node_modules 54 | run: yarn install --frozen-lockfile 55 | - name: Install node_modules (example/) 56 | run: yarn install --frozen-lockfile --cwd example 57 | 58 | - name: Run TypeScript # Reviewdog tsc errorformat: %f:%l:%c - error TS%n: %m 59 | run: | 60 | yarn typescript | reviewdog -name="tsc" -efm="%f(%l,%c): error TS%n: %m" -reporter="github-pr-review" -filter-mode="nofilter" -fail-on-error -tee 61 | env: 62 | REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} 63 | 64 | - name: Run TypeScript in example/ # Reviewdog tsc errorformat: %f:%l:%c - error TS%n: %m 65 | run: | 66 | cd example && yarn typescript | reviewdog -name="tsc" -efm="%f(%l,%c): error TS%n: %m" -reporter="github-pr-review" -filter-mode="nofilter" -fail-on-error -tee && cd .. 67 | env: 68 | REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} 69 | 70 | lint: 71 | name: Lint JS (eslint, prettier) 72 | runs-on: ubuntu-latest 73 | steps: 74 | - uses: actions/checkout@v2 75 | 76 | - name: Get yarn cache directory path 77 | id: yarn-cache-dir-path 78 | run: echo "::set-output name=dir::$(yarn cache dir)" 79 | - name: Restore node_modules from cache 80 | uses: actions/cache@v2 81 | id: yarn-cache 82 | with: 83 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 84 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 85 | restore-keys: | 86 | ${{ runner.os }}-yarn- 87 | 88 | - name: Install node_modules 89 | run: yarn install --frozen-lockfile 90 | - name: Install node_modules (example/) 91 | run: yarn install --frozen-lockfile --cwd example 92 | 93 | - name: Run ESLint 94 | run: yarn lint -f @jamesacarr/github-actions 95 | 96 | - name: Run ESLint with auto-fix 97 | run: yarn lint --fix 98 | 99 | - name: Run ESLint in example/ 100 | run: cd example && yarn lint -f @jamesacarr/github-actions && cd .. 101 | 102 | - name: Run ESLint in example/ with auto-fix 103 | run: cd example && yarn lint --fix && cd .. 104 | 105 | - name: Verify no files have changed after auto-fix 106 | run: git diff --exit-code HEAD 107 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # XDE 6 | .expo/ 7 | 8 | # VSCode 9 | .vscode/ 10 | jsconfig.json 11 | 12 | # Xcode 13 | # 14 | build/ 15 | *.pbxuser 16 | !default.pbxuser 17 | *.mode1v3 18 | !default.mode1v3 19 | *.mode2v3 20 | !default.mode2v3 21 | *.perspectivev3 22 | !default.perspectivev3 23 | xcuserdata 24 | *.xccheckout 25 | *.moved-aside 26 | DerivedData 27 | *.hmap 28 | *.ipa 29 | *.xcuserstate 30 | project.xcworkspace 31 | 32 | # Android/IJ 33 | # 34 | .idea 35 | .gradle 36 | local.properties 37 | android.iml 38 | 39 | # Cocoapods 40 | # 41 | example/ios/Pods 42 | 43 | # node.js 44 | # 45 | node_modules/ 46 | npm-debug.log 47 | yarn-debug.log 48 | yarn-error.log 49 | 50 | # BUCK 51 | buck-out/ 52 | \.buckd/ 53 | android/app/libs 54 | android/keystores/debug.keystore 55 | 56 | # Expo 57 | .expo/* 58 | 59 | # generated by bob 60 | /lib 61 | 62 | # Built application files 63 | *.apk 64 | *.aar 65 | *.ap_ 66 | *.aab 67 | 68 | # Files for the ART/Dalvik VM 69 | *.dex 70 | 71 | # Java class files 72 | *.class 73 | 74 | # Generated files 75 | bin/ 76 | gen/ 77 | out/ 78 | # Uncomment the following line in case you need and you don't have the release build type files in your app 79 | # release/ 80 | 81 | # Gradle files 82 | .gradle/ 83 | build/ 84 | 85 | # Local configuration file (sdk path, etc) 86 | local.properties 87 | 88 | # Proguard folder generated by Eclipse 89 | proguard/ 90 | 91 | # Log Files 92 | *.log 93 | 94 | # Android Studio Navigation editor temp files 95 | .navigation/ 96 | 97 | # Android Studio captures folder 98 | captures/ 99 | 100 | # IntelliJ 101 | *.iml 102 | .idea/workspace.xml 103 | .idea/tasks.xml 104 | .idea/gradle.xml 105 | .idea/assetWizardSettings.xml 106 | .idea/dictionaries 107 | .idea/libraries 108 | # Android Studio 3 in .gitignore file. 109 | .idea/caches 110 | .idea/modules.xml 111 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 112 | .idea/navEditor.xml 113 | 114 | # Keystore files 115 | # Uncomment the following lines if you do not want to check your keystore files in. 116 | #*.jks 117 | #*.keystore 118 | 119 | # External native build folder generated in Android Studio 2.2 and later 120 | .externalNativeBuild 121 | .cxx/ 122 | 123 | # Google Services (e.g. APIs or Firebase) 124 | # google-services.json 125 | 126 | # Freeline 127 | freeline.py 128 | freeline/ 129 | freeline_project_description.json 130 | 131 | # fastlane 132 | fastlane/report.xml 133 | fastlane/Preview.html 134 | fastlane/screenshots 135 | fastlane/test_output 136 | fastlane/readme.md 137 | 138 | # Version control 139 | vcs.xml 140 | 141 | # lint 142 | lint/intermediates/ 143 | lint/generated/ 144 | lint/outputs/ 145 | lint/tmp/ 146 | # lint/reports/ 147 | 148 | # Android Profiling 149 | *.hprof 150 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Marc Rousavy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-native-bignumber 6 | 7 | 8 | 9 | # 🔢 react-native-bignumber 10 | 11 | The fastest Big Number library for React Native. 12 | 13 | * 🏎️ Up to 300x faster than all other solutions 14 | * ⚡️ Lightning fast implementation with pure C++ and JSI 15 | * 🧪 Well tested in JS and C++ (OpenSSL) 16 | * 💰 Made for crypto apps and Wallets 17 | * 🤌 Up to 5x smaller in JS-bundle size 18 | * 🔢 Store numbers as big as your Phone's RAM can store 19 | * 🔁 Easy drop-in replacement for [BN.js](https://github.com/indutny/bn.js/) 20 | 21 | ## Installation 22 | 23 |

24 | React Native   25 |

26 | 27 | ```sh 28 | yarn add react-native-bignumber 29 | cd ios && pod install 30 | ``` 31 | 32 |

33 | Expo   34 |

35 | 36 | ```sh 37 | expo install react-native-bignumber 38 | expo prebuild 39 | ``` 40 | 41 | ## Usage 42 | 43 | ### ..as a normal library 44 | 45 | The exposed `BN` class is used to create new BigNumber instances from strings (binary, hex, decimal), ArrayBuffers, Buffers, numbers, or other BigNumber instances. 46 | 47 | ```ts 48 | import { BN } from 'react-native-bignumber' 49 | 50 | const a = new BN(3274556) 51 | const b = new BN(9856712) 52 | const c = a.mul(b) // 32.276.355.419.872 53 | ``` 54 | 55 | Refer to [BN.js' documentation](https://github.com/indutny/bn.js/#instructions) for a full API reference and usage guide. 56 | 57 | For example, this is how you calculate large Fibonacci numbers: 58 | 59 | ```ts 60 | function fibonacci(n: number): BN { 61 | let prev = new BN(0) 62 | let prevPrev = new BN(1) 63 | let number = new BN(1) 64 | 65 | for (let i = 1; i < n; i++) { 66 | prevPrev = prev 67 | prev = number 68 | number = prevPrev.add(prev) 69 | } 70 | 71 | return number 72 | } 73 | 74 | const f = fibonacci(50) // 12.586.269.025 75 | ``` 76 | 77 | ### ..as a drop-in replacement 78 | 79 | Since popular libraries like [ethers.js](https://github.com/ethers-io/ethers.js/) or [elliptic](https://github.com/indutny/elliptic) use [BN.js](https://github.com/indutny/bn.js/) under the hood, react-native-bignumber exposes exactly the same API as [BN.js](https://github.com/indutny/bn.js/) so it can be used as a drop-in replacement and promises much greater speed at common crypto operations. 80 | 81 | In your `babel.config.js`, add a module resolver to replace `bn.js` with `react-native-bignumber`: 82 | 83 | ```diff 84 | +const path = require('path'); 85 | 86 | module.exports = { 87 | presets: ['module:metro-react-native-babel-preset'], 88 | plugins: [ 89 | + [ 90 | + 'module-resolver', 91 | + { 92 | + alias: { 93 | + 'bn.js': 'react-native-bignumber', 94 | + }, 95 | + }, 96 | + ], 97 | ... 98 | ], 99 | }; 100 | ``` 101 | 102 | Now, all imports for `bn.js` will be resolved as `react-native-bignumber` instead. 103 | 104 | In the Exodus app, this single line change reduced app launch time by **4 seconds**! 🚀 105 | 106 | ## Community Discord 107 | 108 | [Join the Margelo Community Discord](https://discord.gg/6CSHz2qAvA) to chat about react-native-bignumber or other Margelo libraries. 109 | 110 | ## Sponsors 111 | 112 | 113 | Exodus 114 | 115 | 116 | This library is supported by [**Exodus**](https://exodus.com). 117 | Send, receive, and exchange Bitcoin and 160+ cryptocurrencies with ease on the world's leading Desktop, Mobile and Hardware crypto wallets: [exodus.com](https://www.exodus.com/) 118 | 119 | ## Adopting at scale 120 | 121 | react-native-bignumber was built at Margelo, an elite app development agency. For enterprise support or other business inquiries, contact us at hello@margelo.io! 122 | -------------------------------------------------------------------------------- /android/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project("react-native-bignumber") 2 | cmake_minimum_required(VERSION 3.9.0) 3 | 4 | set(PACKAGE_NAME "react-native-bignumber") 5 | set(BUILD_DIR ${CMAKE_SOURCE_DIR}/build) 6 | set(CMAKE_CXX_STANDARD 17) 7 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 8 | 9 | # Consume shared libraries and headers from prefabs 10 | find_package(fbjni REQUIRED CONFIG) 11 | find_package(ReactAndroid REQUIRED CONFIG) 12 | find_package(openssl REQUIRED CONFIG) 13 | find_library(LOG_LIB log) 14 | 15 | include_directories( 16 | "../cpp" 17 | "../cpp/BigNumber" 18 | "../cpp/JSI Utils" 19 | "../cpp/Utils" 20 | "${NODE_MODULES_DIR}/react-native/ReactAndroid/src/main/jni/react/turbomodule" 21 | "${NODE_MODULES_DIR}/react-native/ReactCommon" 22 | "${NODE_MODULES_DIR}/react-native/ReactCommon/callinvoker" 23 | "${NODE_MODULES_DIR}/react-native/ReactCommon/jsi" 24 | "${NODE_MODULES_DIR}/react-native/ReactCommon/turbomodule/core" 25 | "${NODE_MODULES_DIR}/react-native/ReactCommon/react/nativemodule/core" 26 | ) 27 | 28 | add_library( 29 | ${PACKAGE_NAME} 30 | SHARED 31 | "src/main/cpp/cpp-adapter.cpp" 32 | "../cpp/MGBigNumberHostObject.cpp" 33 | "../cpp/JSI Utils/TypedArray.cpp" 34 | "../cpp/Utils/MGDispatchQueue.cpp" 35 | "../cpp/JSI Utils/MGThreadAwareHostObject.cpp" 36 | "../cpp/JSI Utils/MGSmartHostObject.cpp" 37 | "../cpp/BigNumber/MGBigNumber.cpp" 38 | "../cpp/Utils/MGBigNumHelper.cpp" 39 | "../cpp/BigNumber/MGRedBigNum.cpp" 40 | "../cpp/BigNumber/MGModContext.cpp" 41 | ) 42 | 43 | set_target_properties( 44 | ${PACKAGE_NAME} 45 | PROPERTIES 46 | CXX_STANDARD 17 47 | CXX_EXTENSIONS OFF 48 | POSITION_INDEPENDENT_CODE ON 49 | ) 50 | 51 | target_link_libraries( 52 | ${PACKAGE_NAME} 53 | ${LOG_LIB} 54 | fbjni::fbjni 55 | ReactAndroid::jsi 56 | android 57 | openssl::crypto 58 | openssl::ssl 59 | ) 60 | 61 | if (ReactAndroid_VERSION_MINOR GREATER_EQUAL 76) 62 | target_link_libraries( 63 | ${PACKAGE_NAME} 64 | ReactAndroid::reactnative 65 | ) 66 | else () 67 | target_link_libraries( 68 | ${PACKAGE_NAME} 69 | ReactAndroid::reactnativejni 70 | ReactAndroid::turbomodulejsijni 71 | ReactAndroid::react_nativemodule_core 72 | ) 73 | endif () -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | import java.nio.file.Paths 2 | 3 | static def findNodeModules(baseDir) { 4 | def basePath = baseDir.toPath().normalize() 5 | // Node's module resolution algorithm searches up to the root directory, 6 | // after which the base path will be null 7 | while (basePath) { 8 | def nodeModulesPath = Paths.get(basePath.toString(), "node_modules") 9 | def reactNativePath = Paths.get(nodeModulesPath.toString(), "react-native") 10 | if (nodeModulesPath.toFile().exists() && reactNativePath.toFile().exists()) { 11 | return nodeModulesPath.toString() 12 | } 13 | basePath = basePath.getParent() 14 | } 15 | throw new GradleException("BigNumber: Failed to find node_modules/ path!") 16 | } 17 | 18 | def nodeModules = findNodeModules(projectDir) 19 | logger.warn("BigNumber: node_modules/ found at: ${nodeModules}") 20 | 21 | buildscript { 22 | repositories { 23 | google() 24 | jcenter() 25 | maven { 26 | url "https://plugins.gradle.org/m2/" 27 | } 28 | mavenCentral() 29 | maven { url 'https://jitpack.io' } 30 | } 31 | 32 | dependencies { 33 | classpath 'com.android.tools.build:gradle:7.1.2' 34 | } 35 | } 36 | 37 | apply plugin: 'com.android.library' 38 | 39 | def getExtOrDefault(name) { 40 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['BigNumber_' + name] 41 | } 42 | 43 | def getExtOrIntegerDefault(name) { 44 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['BigNumber_' + name]).toInteger() 45 | } 46 | 47 | def reactNativeArchitectures() { 48 | def value = project.getProperties().get("reactNativeArchitectures") 49 | return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] 50 | } 51 | 52 | 53 | def reactProperties = new Properties() 54 | file("$nodeModules/react-native/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) } 55 | 56 | android { 57 | compileSdkVersion getExtOrIntegerDefault('compileSdkVersion') 58 | buildToolsVersion getExtOrDefault('buildToolsVersion') 59 | ndkVersion getExtOrDefault('ndkVersion') 60 | 61 | buildFeatures { 62 | prefab true 63 | } 64 | 65 | defaultConfig { 66 | minSdkVersion getExtOrIntegerDefault('minSdkVersion') 67 | targetSdkVersion getExtOrIntegerDefault('targetSdkVersion') 68 | externalNativeBuild { 69 | cmake { 70 | cppFlags "-fexceptions", "-frtti", "-std=c++1y", "-DONANDROID", "-DONANDROID" 71 | arguments '-DANDROID_STL=c++_shared', 72 | "-DNODE_MODULES_DIR=${nodeModules}" 73 | } 74 | } 75 | ndk { 76 | abiFilters (*reactNativeArchitectures()) 77 | } 78 | } 79 | 80 | externalNativeBuild { 81 | cmake { 82 | path "CMakeLists.txt" 83 | } 84 | } 85 | packagingOptions { 86 | jniLibs { 87 | excludes += [ 88 | '**/libc++_shared.so', 89 | '**/libfbjni.so', 90 | '**/libreactnativejni.so', 91 | '**/libjsi.so', 92 | '**/libreact_nativemodule_core.so', 93 | '**/libturbomodulejsijni.so', 94 | '**/libreactnative.so' 95 | ] 96 | } 97 | resources { 98 | excludes += ['**/MANIFEST.MF'] 99 | } 100 | exclude 'META-INF/LICENSE.md' 101 | } 102 | 103 | 104 | buildTypes { 105 | /*release { 106 | minifyEnabled false 107 | }*/ 108 | } 109 | compileOptions { 110 | sourceCompatibility JavaVersion.VERSION_1_8 111 | targetCompatibility JavaVersion.VERSION_1_8 112 | } 113 | 114 | buildFeatures { 115 | prefab true 116 | } 117 | /*lint { 118 | disable 'GradleCompatible' 119 | }*/ 120 | } 121 | 122 | repositories { 123 | mavenCentral() 124 | google() 125 | } 126 | 127 | dependencies { 128 | // Add a dependency on OpenSSL 129 | implementation "io.github.ronickg:openssl:3.3.2" 130 | 131 | implementation "com.facebook.react:react-android:0.71.6" 132 | implementation "com.facebook.react:hermes-android:0.71.6" 133 | } -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | BigNumber_compileSdkVersion=30 2 | BigNumber_buildToolsVersion=30.0.2 3 | BigNumber_targetSdkVersion=30 4 | BigNumber_ndkVersion=21.4.7075529 5 | BigNumber_minSdkVersion=23 6 | android.useAndroidX=true 7 | 8 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=`expr $i + 1` 158 | done 159 | case $i in 160 | 0) set -- ;; 161 | 1) set -- "$args0" ;; 162 | 2) set -- "$args0" "$args1" ;; 163 | 3) set -- "$args0" "$args1" "$args2" ;; 164 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=`save "$@"` 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | exec "$JAVACMD" "$@" 184 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/src/main/cpp/cpp-adapter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "MGBigNumberHostObject.h" 6 | 7 | using namespace facebook; 8 | 9 | class BigNumberCppAdapter : public jni::HybridClass { 10 | public: 11 | static auto constexpr kJavaDescriptor = "Lcom/margelo/bignumber/BigNumberModule;"; 12 | 13 | static jni::local_ref::jhybriddata> initHybrid( 14 | jni::alias_ref jThis) { 15 | return makeCxxInstance(); 16 | } 17 | 18 | explicit BigNumberCppAdapter() { 19 | } 20 | 21 | void install(jsi::Runtime& runtime, std::shared_ptr jsCallInvoker) { 22 | auto workerQueue = std::make_shared("Margelo MGBigNumber Thread"); 23 | auto hostObject = std::make_shared(jsCallInvoker, workerQueue); 24 | auto object = jsi::Object::createFromHostObject(runtime, hostObject); 25 | runtime.global().setProperty(runtime, "__BigNumberProxy", std::move(object)); 26 | } 27 | 28 | void nativeInstall(jlong jsiPtr, jni::alias_ref 29 | jsCallInvokerHolder) { 30 | auto jsCallInvoker = jsCallInvokerHolder->cthis()->getCallInvoker(); 31 | auto runtime = reinterpret_cast(jsiPtr); 32 | if (runtime) { 33 | install(*runtime, jsCallInvoker); 34 | } 35 | // if runtime was nullptr, MGBigNumber will not be installed. This should only happen while Remote Debugging (Chrome), but will be weird either way. 36 | } 37 | 38 | static void registerNatives() { 39 | registerHybrid({ 40 | makeNativeMethod("initHybrid", BigNumberCppAdapter::initHybrid), 41 | makeNativeMethod("nativeInstall", BigNumberCppAdapter::nativeInstall) 42 | }); 43 | } 44 | 45 | private: 46 | friend HybridBase; 47 | }; 48 | 49 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { 50 | return facebook::jni::initialize(vm, [] { 51 | BigNumberCppAdapter::registerNatives(); 52 | }); 53 | } 54 | -------------------------------------------------------------------------------- /android/src/main/java/com/margelo/bignumber/BigNumberModule.java: -------------------------------------------------------------------------------- 1 | package com.margelo.bignumber; 2 | 3 | import android.util.Log; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | 8 | import com.facebook.jni.HybridData; 9 | import com.facebook.proguard.annotations.DoNotStrip; 10 | import com.facebook.react.bridge.JavaScriptContextHolder; 11 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 12 | import com.facebook.react.bridge.ReactApplicationContext; 13 | import com.facebook.react.bridge.ReactMethod; 14 | import com.facebook.react.module.annotations.ReactModule; 15 | import com.facebook.react.turbomodule.core.CallInvokerHolderImpl; 16 | import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder; 17 | 18 | @ReactModule(name = BigNumberModule.NAME) 19 | public class BigNumberModule extends ReactContextBaseJavaModule { 20 | public static final String NAME = "BigNumber"; 21 | 22 | @DoNotStrip 23 | private HybridData mHybridData; 24 | 25 | private native HybridData initHybrid(); 26 | 27 | public BigNumberModule(ReactApplicationContext reactContext) { 28 | super(reactContext); 29 | } 30 | 31 | @NonNull 32 | @Override 33 | public String getName() { 34 | return NAME; 35 | } 36 | 37 | @ReactMethod(isBlockingSynchronousMethod = true) 38 | public boolean install() { 39 | try { 40 | if (mHybridData != null) { 41 | return false; 42 | } 43 | Log.i(NAME, "Loading C++ library..."); 44 | System.loadLibrary("react-native-bignumber"); 45 | 46 | JavaScriptContextHolder jsContext = getReactApplicationContext().getJavaScriptContextHolder(); 47 | CallInvokerHolderImpl jsCallInvokerHolder = (CallInvokerHolderImpl) getReactApplicationContext() 48 | .getCatalystInstance() 49 | .getJSCallInvokerHolder(); 50 | 51 | 52 | Log.i(NAME, "Installing JSI Bindings for react-native-bignumber..."); 53 | mHybridData = initHybrid(); 54 | nativeInstall(jsContext.get(), jsCallInvokerHolder); 55 | Log.i(NAME, "Successfully installed JSI Bindings for react-native-bignumber!"); 56 | 57 | return true; 58 | } catch (Exception exception) { 59 | Log.e(NAME, "Failed to install JSI Bindings for react-native-bignumber!", exception); 60 | return false; 61 | } 62 | } 63 | 64 | public void destroy() { 65 | if (mHybridData == null) { 66 | return; 67 | } 68 | mHybridData.resetNative(); 69 | } 70 | 71 | private native void nativeInstall(long jsiPtr, CallInvokerHolderImpl jsCallInvokerHolder); 72 | } 73 | -------------------------------------------------------------------------------- /android/src/main/java/com/margelo/bignumber/BigNumberPackage.java: -------------------------------------------------------------------------------- 1 | package com.margelo.bignumber; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import com.facebook.react.ReactPackage; 6 | import com.facebook.react.bridge.NativeModule; 7 | import com.facebook.react.bridge.ReactApplicationContext; 8 | import com.facebook.react.uimanager.ViewManager; 9 | 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class BigNumberPackage implements ReactPackage { 14 | @NonNull 15 | @Override 16 | public List createNativeModules(@NonNull ReactApplicationContext reactContext) { 17 | return Collections.singletonList(new BigNumberModule(reactContext)); 18 | } 19 | 20 | @NonNull 21 | @Override 22 | public List createViewManagers(@NonNull ReactApplicationContext reactContext) { 23 | return Collections.emptyList(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /cpp/BigNumber/MGBigNumber.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 08/03/2022. 3 | // 4 | 5 | #include "MGBigNumber.h" 6 | #include "MGBigNumHelper.h" 7 | #include 8 | 9 | namespace margelo 10 | { 11 | 12 | MGBigNumber::MGBigNumber(BN_CTX *ctx) 13 | { 14 | this->ctx = ctx; 15 | this->bign = BN_new(); 16 | BN_zero(this->bign); 17 | } 18 | 19 | MGBigNumber::MGBigNumber(const unsigned char *s, int len, int base, bool le, BN_CTX *ctx) 20 | { 21 | this->ctx = ctx; 22 | this->bign = BN_new(); 23 | 24 | if (base == 36) 25 | { 26 | if (le) 27 | { 28 | BN_zero(this->bign); 29 | for (int i = len - 1; i >= 0; --i) 30 | { 31 | int value = s[i]; 32 | BN_mul_word(this->bign, 36); 33 | BN_add_word(this->bign, value); 34 | } 35 | } 36 | else 37 | { 38 | BN_zero(this->bign); 39 | for (int i = 0; i < len; ++i) 40 | { 41 | int value = s[i]; 42 | BN_mul_word(this->bign, 36); 43 | BN_add_word(this->bign, value); 44 | } 45 | } 46 | } 47 | 48 | if (base == 16) 49 | { 50 | if (le) 51 | { 52 | BN_lebin2bn(s, len, this->bign); 53 | } 54 | else 55 | { 56 | BN_bin2bn(s, len, this->bign); 57 | } 58 | } 59 | } 60 | 61 | MGBigNumber::MGBigNumber(std::string numberAsString, int base, BN_CTX *ctx) 62 | { 63 | this->ctx = ctx; 64 | this->bign = BN_new(); 65 | 66 | if (base == 10) 67 | { 68 | BN_dec2bn(&(this->bign), numberAsString.c_str()); 69 | } 70 | else if (base == 2) 71 | { 72 | // openSSL doesnt have method that can parse '010110'(binary) format 73 | // so I first change binary to hex then use BN_hex2bn to parse it 74 | // changing binary to hex is simple just simply concatenate the adjacent 4 bits and change to hex |0010|1100 = 2C 75 | bool negative = false; 76 | if (numberAsString.front() == '-') 77 | { 78 | negative = true; 79 | numberAsString.erase(0, 1); 80 | } 81 | // Adding leading 0 so that it equals 0 mod 4 82 | int needToAdd = (4 - (numberAsString.size() % 4)) % 4; 83 | while (needToAdd--) 84 | { 85 | numberAsString = "0" + numberAsString; 86 | } 87 | int n = numberAsString.size() / 4 + 1; 88 | char *inHex = new char[n]; 89 | inHex[n - 1] = '\0'; 90 | for (int i = 0; i < n - 1; ++i) 91 | { 92 | int value = 0; 93 | int beginning = i * 4; 94 | for (int j = 0; j < 4; ++j) 95 | { 96 | value *= 2; 97 | if (numberAsString[beginning + j] == '1') 98 | { 99 | value++; 100 | } 101 | } 102 | if (value <= 9) 103 | { 104 | inHex[i] = '0' + value; 105 | } 106 | else 107 | { 108 | inHex[i] = 'a' + value - 10; 109 | } 110 | } 111 | 112 | BN_hex2bn(&(this->bign), inHex); 113 | 114 | // set negative if input string had '-' at the beginning 115 | if (negative) 116 | { 117 | BN_set_negative(this->bign, 1); 118 | } 119 | 120 | delete[] inHex; 121 | } 122 | else if (base == 16) 123 | { 124 | BN_hex2bn(&(this->bign), numberAsString.c_str()); 125 | } 126 | else if (base == 36) 127 | { 128 | bool negative = false; 129 | if (numberAsString.front() == '-') 130 | { 131 | negative = true; 132 | numberAsString.erase(0, 1); 133 | } 134 | BN_zero(this->bign); 135 | for (char c : numberAsString) 136 | { 137 | int value = c - '0'; 138 | if (c >= 'A' && c <= 'Z') 139 | { 140 | value = c - 'A' + 10; 141 | } 142 | if (c >= 'a' && c <= 'z') 143 | { 144 | value = c - 'a' + 10; 145 | } 146 | BN_mul_word(this->bign, 36); 147 | BN_add_word(this->bign, value); 148 | } 149 | BN_set_negative(this->bign, negative); 150 | } 151 | } 152 | 153 | MGBigNumber::MGBigNumber(int value, BN_CTX *ctx) 154 | { 155 | 156 | this->ctx = ctx; 157 | this->bign = BN_new(); 158 | BN_set_word(this->bign, abs(value)); 159 | if (value < 0) 160 | { 161 | BN_set_negative(this->bign, 1); 162 | } 163 | } 164 | 165 | MGBigNumber::MGBigNumber(const MGBigNumber &other) 166 | { 167 | this->ctx = other.ctx; 168 | BN_copy(this->bign, other.bign); 169 | } 170 | 171 | jsi::Value MGBigNumber::get(jsi::Runtime &runtime, const jsi::PropNameID &propNameId) 172 | { 173 | std::string name = propNameId.utf8(runtime); 174 | if (name == "isInternalBigNum") 175 | { 176 | return jsi::Value(runtime, true); 177 | } 178 | if (name == "toString") 179 | { 180 | char *str = BN_bn2dec(this->bign); 181 | std::string strRep(str); 182 | delete[] str; 183 | jsi::String res = jsi::String::createFromUtf8(runtime, strRep); 184 | return jsi::Value(runtime, res); 185 | } 186 | if (name == "toStringTag") 187 | { 188 | jsi::String res = jsi::String::createFromUtf8(runtime, "[object MGBigNumber]"); 189 | return jsi::Value(runtime, res); 190 | } 191 | if (name == "value") 192 | { 193 | return jsi::Function::createFromHostFunction(runtime, propNameId, 0, [&](jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *arguments, size_t count) -> jsi::Value 194 | { return thisValue.getObject(runtime).getProperty(runtime, "toString"); }); 195 | } 196 | return jsi::Value::undefined(); 197 | } 198 | 199 | std::vector MGBigNumber::getPropertyNames( 200 | jsi::Runtime &runtime) 201 | { 202 | std::vector propertyNames; 203 | 204 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "isInternalBigNum")); 205 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "toString")); 206 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "toStringTag")); 207 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "value")); 208 | return propertyNames; 209 | } 210 | 211 | void MGBigNumber::set(jsi::Runtime &runtime, const jsi::PropNameID &propNameId, const jsi::Value & value) { 212 | // do nothing; 213 | } 214 | 215 | 216 | MGBigNumber::~MGBigNumber() 217 | { 218 | BN_free(this->bign); 219 | } 220 | 221 | } // namespace margelo 222 | -------------------------------------------------------------------------------- /cpp/BigNumber/MGBigNumber.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 08/03/2022. 3 | // 4 | 5 | #ifndef BIGNUMBEREXAMPLE_MGBIGNUMBER_H 6 | #define BIGNUMBEREXAMPLE_MGBIGNUMBER_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include "MGDispatchQueue.h" 12 | #include "MGSmartHostObject.h" 13 | #include 14 | #include 15 | 16 | namespace margelo 17 | { 18 | namespace jsi = facebook::jsi; 19 | 20 | class MGBigNumber : public jsi::HostObject 21 | { 22 | public: 23 | explicit MGBigNumber(BN_CTX *ctx); 24 | 25 | explicit MGBigNumber(std::string, int base, BN_CTX *ctx); 26 | 27 | explicit MGBigNumber(const unsigned char *s, int len, int base, bool le, BN_CTX *ctx); 28 | 29 | explicit MGBigNumber(int value, BN_CTX *ctx); 30 | 31 | explicit MGBigNumber(const MGBigNumber &); 32 | 33 | virtual ~MGBigNumber(); 34 | 35 | virtual void set(jsi::Runtime &runtime, const jsi::PropNameID &propNameId, const jsi::Value & value) override; 36 | virtual jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &propNameId); 37 | virtual std::vector getPropertyNames(jsi::Runtime &runtime); 38 | 39 | BIGNUM *bign; 40 | BN_CTX *ctx; 41 | }; 42 | 43 | } // namespace margelo 44 | 45 | #endif // BIGNUMBEREXAMPLE_MGBIGNUMBER_H 46 | -------------------------------------------------------------------------------- /cpp/BigNumber/MGModContext.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 17/03/2022. 3 | // 4 | 5 | #include "MGModContext.h" 6 | #include "MGBigNumber.h" 7 | #include "MGBigNumberHostObject.h" 8 | 9 | namespace margelo 10 | { 11 | std::string MGModContext::k256 = std::string("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"); 12 | std::string MGModContext::p224 = std::string("ffffffffffffffffffffffffffffffff000000000000000000000001"); 13 | std::string MGModContext::p192 = std::string("fffffffffffffffffffffffffffffffeffffffffffffffff"); 14 | std::string MGModContext::p25519 = std::string("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed"); 15 | 16 | MGModContext::MGModContext(int number, BN_CTX *ctx) 17 | { 18 | this->mctx = BN_MONT_CTX_new(); 19 | this->m = BN_new(); 20 | BN_set_word(this->m, number); 21 | BN_MONT_CTX_set(this->mctx, this->m, ctx); 22 | } 23 | MGModContext::MGModContext(BIGNUM *bign, BN_CTX *ctx) 24 | { 25 | this->mctx = BN_MONT_CTX_new(); 26 | this->m = BN_new(); 27 | BN_copy(this->m, bign); 28 | BN_MONT_CTX_set(this->mctx, this->m, ctx); 29 | } 30 | 31 | std::vector MGModContext::getPropertyNames( 32 | jsi::Runtime &runtime) 33 | { 34 | std::vector propertyNames; 35 | 36 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "isModContext")); 37 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "toString")); 38 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "toStringTag")); 39 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "value")); 40 | return propertyNames; 41 | } 42 | 43 | jsi::Value MGModContext::get(jsi::Runtime &runtime, const jsi::PropNameID &propNameId) 44 | { 45 | std::string name = propNameId.utf8(runtime); 46 | if (name == "isModContext") 47 | { 48 | return jsi::Value(runtime, true); 49 | } 50 | // Why "m"? https://github.com/indutny/bn.js/blob/5d5532d9fb7192b5d2545bdb2aa024ca1822a313/lib/bn.js#L3244 51 | if (name == "m") 52 | { 53 | std::shared_ptr res = std::make_shared(MGBigNumberHostObject::bn_ctx); 54 | BN_copy(res->bign, this->m); 55 | jsi::Object obj = jsi::Object::createFromHostObject(runtime, res); 56 | // not called often no need to cache 57 | return runtime.global().getPropertyAsFunction(runtime, "__createBN").call(runtime, obj); 58 | } 59 | if (name == "split") 60 | { 61 | throw jsi::JSError(runtime, "split has not been implemented yet"); 62 | } 63 | if (name == "reduce") 64 | { 65 | throw jsi::JSError(runtime, "reduce has not been implemented yet"); 66 | } 67 | if (name == "toString") 68 | { 69 | char *str = BN_bn2dec(this->m); 70 | std::string strRep(str); 71 | delete[] str; 72 | jsi::String res = jsi::String::createFromUtf8(runtime, strRep); 73 | return jsi::Value(runtime, res); 74 | } 75 | if (name == "toStringTag") 76 | { 77 | jsi::String res = jsi::String::createFromUtf8(runtime, "[object MGModContext]"); 78 | return jsi::Value(runtime, res); 79 | } 80 | if (name == "value") 81 | { 82 | return jsi::Function::createFromHostFunction(runtime, propNameId, 0, [&](jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *arguments, size_t count) -> jsi::Value 83 | { return thisValue.getObject(runtime).getProperty(runtime, "toString"); }); 84 | } 85 | return jsi::Value::undefined(); 86 | } 87 | 88 | MGModContext::~MGModContext() 89 | { 90 | BN_MONT_CTX_free(this->mctx); 91 | BN_free(this->m); 92 | } 93 | } // namespace margelo 94 | -------------------------------------------------------------------------------- /cpp/BigNumber/MGModContext.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 17/03/2022. 3 | // 4 | 5 | #ifndef BIGNUMBEREXAMPLE_MGMODCONTEXT_H 6 | #define BIGNUMBEREXAMPLE_MGMODCONTEXT_H 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace margelo 13 | { 14 | namespace jsi = facebook::jsi; 15 | struct MGModContext : jsi::HostObject 16 | { 17 | MGModContext(int number, BN_CTX *ctx); 18 | MGModContext(BIGNUM *bign, BN_CTX *ctx); 19 | virtual ~MGModContext(); 20 | 21 | jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &propNameId); 22 | virtual std::vector getPropertyNames(jsi::Runtime &runtime); 23 | 24 | static std::string k256; 25 | static std::string p224; 26 | static std::string p192; 27 | static std::string p25519; 28 | 29 | BN_MONT_CTX *mctx; 30 | BIGNUM *m; 31 | }; 32 | } // namespace margelo 33 | 34 | #endif // BIGNUMBEREXAMPLE_MGMODCONTEXT_H 35 | -------------------------------------------------------------------------------- /cpp/BigNumber/MGRedBigNum.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 17/03/2022. 3 | // 4 | 5 | #include "MGRedBigNum.h" 6 | 7 | namespace margelo 8 | { 9 | 10 | MGRedBigNum::MGRedBigNum(BN_CTX *ctx, BN_MONT_CTX *mctx, BIGNUM *m) : MGBigNumber(ctx) 11 | { 12 | BN_zero(this->bign); 13 | this->ctx = ctx; 14 | this->mctx = mctx; 15 | this->m = m; 16 | } 17 | 18 | MGRedBigNum::MGRedBigNum(BIGNUM *bign, bool force, BN_CTX *ctx, BN_MONT_CTX *mctx, BIGNUM *m) : MGBigNumber(ctx) 19 | { 20 | this->bign = BN_copy(this->bign, bign); 21 | // Sometimes we already have montgomery form so we force that format without 22 | // convertion. 23 | if (!force) 24 | { 25 | BN_to_montgomery(this->bign, this->bign, mctx, ctx); 26 | } 27 | this->ctx = ctx; 28 | this->mctx = mctx; 29 | this->m = m; 30 | } 31 | 32 | MGRedBigNum::MGRedBigNum(const MGRedBigNum &other) : MGBigNumber(ctx) 33 | { 34 | this->bign = BN_copy(this->bign, other.bign); 35 | this->ctx = other.ctx; 36 | this->mctx = other.mctx; 37 | this->m = other.m; 38 | } 39 | 40 | MGRedBigNum::~MGRedBigNum() 41 | { // mctx is kept alive on js Side 42 | } 43 | 44 | std::vector MGRedBigNum::getPropertyNames( 45 | jsi::Runtime &runtime) 46 | { 47 | std::vector propertyNames; 48 | 49 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "isInternalRedBigNum")); 50 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "toString")); 51 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "toStringTag")); 52 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "value")); 53 | return propertyNames; 54 | } 55 | 56 | jsi::Value MGRedBigNum::get(jsi::Runtime &runtime, const jsi::PropNameID &propNameId) 57 | { 58 | std::string name = propNameId.utf8(runtime); 59 | if (name == "isInternalRedBigNum") 60 | { 61 | return jsi::Value(runtime, true); 62 | } 63 | if (name == "toString") 64 | { 65 | char *str = BN_bn2dec(this->bign); 66 | std::string strRep(str); 67 | delete[] str; 68 | jsi::String res = jsi::String::createFromUtf8(runtime, strRep); 69 | return jsi::Value(runtime, res); 70 | } 71 | if (name == "toStringTag") 72 | { 73 | jsi::String res = jsi::String::createFromUtf8(runtime, "[object MGRedBigNum]"); 74 | return jsi::Value(runtime, res); 75 | } 76 | if (name == "value") 77 | { 78 | return jsi::Function::createFromHostFunction(runtime, propNameId, 0, [&](jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *arguments, size_t count) -> jsi::Value 79 | { return thisValue.getObject(runtime).getProperty(runtime, "toString"); }); 80 | } 81 | return jsi::Value::undefined(); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /cpp/BigNumber/MGRedBigNum.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 17/03/2022. 3 | // 4 | 5 | #ifndef BIGNUMBEREXAMPLE_MGREDBIGNUM_H 6 | #define BIGNUMBEREXAMPLE_MGREDBIGNUM_H 7 | 8 | #include "MGBigNumber.h" 9 | 10 | namespace margelo 11 | { 12 | namespace jsi = facebook::jsi; 13 | 14 | class MGRedBigNum : public MGBigNumber 15 | { 16 | public: 17 | explicit MGRedBigNum(BN_CTX *ctx, BN_MONT_CTX *mctx, BIGNUM *m); 18 | 19 | explicit MGRedBigNum(BIGNUM *bign, bool force, BN_CTX *ctx, BN_MONT_CTX *mctx, BIGNUM *m); 20 | 21 | explicit MGRedBigNum(const MGRedBigNum &); 22 | 23 | virtual ~MGRedBigNum(); 24 | 25 | virtual jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &propNameId); 26 | virtual std::vector getPropertyNames(jsi::Runtime &runtime); 27 | 28 | BN_MONT_CTX *mctx; 29 | BIGNUM *m; 30 | }; 31 | 32 | } // namespace margelo 33 | 34 | #endif // BIGNUMBEREXAMPLE_MGREDBIGNUM_H 35 | -------------------------------------------------------------------------------- /cpp/JSI Utils/MGJSIMacros.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 24/02/2022. 3 | // 4 | 5 | #ifndef BigNumberEXAMPLE_JSIMACROS_H 6 | #define BigNumberEXAMPLE_JSIMACROS_H 7 | 8 | // if you want to create a new marco use (https://godbolt.org) provide flag -E in right panel 9 | 10 | #define HOST_LAMBDA(name, body) HOST_LAMBDA_CAP(name, [=], body) 11 | 12 | #define HOST_LAMBDA_CAP(name, capture, body) std::make_pair( \ 13 | name, capture(jsi::Runtime &runtime) { \ 14 | const auto func = capture(jsi::Runtime & runtime, const jsi::Value &thisValue, \ 15 | const jsi::Value *arguments, size_t count) \ 16 | ->jsi::Value \ 17 | body; \ 18 | auto propNameID = jsi::PropNameID::forAscii(runtime, name); \ 19 | return jsi::Function::createFromHostFunction(runtime, propNameID, 0, func); \ 20 | }) 21 | 22 | #define JSIF(capture) \ 23 | capture(jsi::Runtime &runtime, const jsi::Value &thisValue, \ 24 | const jsi::Value *arguments, size_t count) \ 25 | ->jsi::Value 26 | 27 | #define JSI_VALUE(name, body) JSI_VALUE_CAP(name, [=], body) 28 | 29 | #define JSI_VALUE_CAP(name, capture, body) std::make_pair(name, capture(jsi::Runtime &runtime) \ 30 | body) 31 | 32 | #endif // BigNumberEXAMPLE_JSIMACROS_H 33 | -------------------------------------------------------------------------------- /cpp/JSI Utils/MGSmartHostObject.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 24/02/2022. 3 | // 4 | 5 | #include "MGSmartHostObject.h" 6 | 7 | namespace margelo 8 | { 9 | 10 | namespace jsi = facebook::jsi; 11 | namespace react = facebook::react; 12 | 13 | std::vector MGSmartHostObject::getPropertyNames( 14 | jsi::Runtime &runtime) 15 | { 16 | std::vector propertyNames; 17 | for (auto field : fields) 18 | { 19 | propertyNames.push_back(jsi::PropNameID::forAscii(runtime, field.first)); 20 | } 21 | return propertyNames; 22 | } 23 | 24 | FieldDefinition buildPair(std::string name, jsi::HostFunctionType &&f) { 25 | auto valueBuilder = [f, name](jsi::Runtime &runtime) { 26 | const auto func = f; 27 | auto propNameID = jsi::PropNameID::forAscii(runtime, name); 28 | return jsi::Function::createFromHostFunction(runtime, propNameID, 0, func); 29 | }; 30 | return std::make_pair(name, valueBuilder); 31 | } 32 | 33 | // TODO(Szymon) maybe add memoization here 34 | jsi::Value MGSmartHostObject::get(jsi::Runtime &runtime, 35 | const jsi::PropNameID &propNameId) 36 | { 37 | auto name = propNameId.utf8(runtime); 38 | for (auto field : fields) 39 | { 40 | auto fieldName = field.first; 41 | if (fieldName == name) 42 | { 43 | return (field.second)(runtime); 44 | } 45 | } 46 | return jsi::Value::undefined(); 47 | } 48 | 49 | } // namespace margelo 50 | -------------------------------------------------------------------------------- /cpp/JSI Utils/MGSmartHostObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 24/02/2022. 3 | // 4 | 5 | #ifndef BigNumberEXAMPLE_SMARTHOSTOBJECT_H 6 | #define BigNumberEXAMPLE_SMARTHOSTOBJECT_H 7 | 8 | #include "MGThreadAwareHostObject.h" 9 | #include "MGJSIMacros.h" 10 | #include 11 | 12 | namespace margelo 13 | { 14 | 15 | namespace jsi = facebook::jsi; 16 | namespace react = facebook::react; 17 | 18 | typedef std::function JSIValueBuilder; 19 | 20 | typedef std::pair FieldDefinition; 21 | 22 | FieldDefinition buildPair(std::string name, jsi::HostFunctionType &&f); 23 | 24 | class JSI_EXPORT MGSmartHostObject : public MGThreadAwareHostObject 25 | { 26 | 27 | public: 28 | MGSmartHostObject(std::shared_ptr jsCallInvoker, 29 | std::shared_ptr workerQueue) 30 | : MGThreadAwareHostObject(jsCallInvoker, workerQueue) 31 | { 32 | } 33 | 34 | virtual ~MGSmartHostObject() 35 | { 36 | } 37 | 38 | std::vector getPropertyNames(jsi::Runtime &runtime); 39 | 40 | jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &propNameId); 41 | 42 | std::vector> fields; 43 | }; 44 | 45 | } // namespace margelo 46 | 47 | #endif // BigNumberEXAMPLE_SMARTHOSTOBJECT_H 48 | -------------------------------------------------------------------------------- /cpp/JSI Utils/MGThreadAwareHostObject.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 24/02/2022. 3 | // 4 | 5 | #include "MGThreadAwareHostObject.h" 6 | 7 | namespace margelo 8 | { 9 | 10 | namespace jsi = facebook::jsi; 11 | 12 | void MGThreadAwareHostObject::runOnWorkerThread(std::function &&job) 13 | { 14 | this->dispatchQueue->dispatch(job); 15 | } 16 | 17 | void MGThreadAwareHostObject::runOnJSThread(std::function &&job) 18 | { 19 | auto callInvoker = this->weakJsCallInvoker.lock(); 20 | if (callInvoker != nullptr) 21 | { 22 | callInvoker->invokeAsync(std::move(job)); 23 | } 24 | } 25 | 26 | } // namespace margelo 27 | -------------------------------------------------------------------------------- /cpp/JSI Utils/MGThreadAwareHostObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 24/02/2022. 3 | // 4 | 5 | #ifndef BigNumberEXAMPLE_THREADAWAREHOSTOBJECT_H 6 | #define BigNumberEXAMPLE_THREADAWAREHOSTOBJECT_H 7 | 8 | #include 9 | #include 10 | #include "MGDispatchQueue.h" 11 | 12 | namespace margelo 13 | { 14 | 15 | namespace jsi = facebook::jsi; 16 | namespace react = facebook::react; 17 | 18 | class JSI_EXPORT MGThreadAwareHostObject : public jsi::HostObject 19 | { 20 | public: 21 | explicit MGThreadAwareHostObject(std::shared_ptr jsCallInvoker, std::shared_ptr workerQueue) : weakJsCallInvoker(jsCallInvoker), dispatchQueue(workerQueue) 22 | { 23 | } 24 | 25 | virtual ~MGThreadAwareHostObject() 26 | { 27 | } 28 | 29 | void runOnWorkerThread(std::function &&job); 30 | void runOnJSThread(std::function &&job); 31 | 32 | protected: 33 | std::weak_ptr weakJsCallInvoker; 34 | std::shared_ptr dispatchQueue; 35 | }; 36 | 37 | } // namespace margelo 38 | 39 | #endif // BigNumberEXAMPLE_THREADAWAREHOSTOBJECT_H 40 | -------------------------------------------------------------------------------- /cpp/JSI Utils/TypedArray.h: -------------------------------------------------------------------------------- 1 | // 2 | // TypedArray.h 3 | // react-native-bignumber 4 | // 5 | // Created by Marc Rousavy on 31.10.21. 6 | // Originally created by Expo (expo-gl) 7 | // 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace jsi = facebook::jsi; 14 | 15 | enum class TypedArrayKind 16 | { 17 | Int8Array, 18 | Int16Array, 19 | Int32Array, 20 | Uint8Array, 21 | Uint8ClampedArray, 22 | Uint16Array, 23 | Uint32Array, 24 | Float32Array, 25 | Float64Array, 26 | }; 27 | 28 | template 29 | class TypedArray; 30 | 31 | template 32 | struct typedArrayTypeMap; 33 | template <> 34 | struct typedArrayTypeMap 35 | { 36 | typedef int8_t type; 37 | }; 38 | template <> 39 | struct typedArrayTypeMap 40 | { 41 | typedef int16_t type; 42 | }; 43 | template <> 44 | struct typedArrayTypeMap 45 | { 46 | typedef int32_t type; 47 | }; 48 | template <> 49 | struct typedArrayTypeMap 50 | { 51 | typedef uint8_t type; 52 | }; 53 | template <> 54 | struct typedArrayTypeMap 55 | { 56 | typedef uint8_t type; 57 | }; 58 | template <> 59 | struct typedArrayTypeMap 60 | { 61 | typedef uint16_t type; 62 | }; 63 | template <> 64 | struct typedArrayTypeMap 65 | { 66 | typedef uint32_t type; 67 | }; 68 | template <> 69 | struct typedArrayTypeMap 70 | { 71 | typedef float type; 72 | }; 73 | template <> 74 | struct typedArrayTypeMap 75 | { 76 | typedef double type; 77 | }; 78 | 79 | void invalidateJsiPropNameIDCache(); 80 | 81 | class TypedArrayBase : public jsi::Object 82 | { 83 | public: 84 | template 85 | using ContentType = typename typedArrayTypeMap::type; 86 | 87 | TypedArrayBase(jsi::Runtime &, size_t, TypedArrayKind); 88 | TypedArrayBase(jsi::Runtime &, const jsi::Object &); 89 | TypedArrayBase(TypedArrayBase &&) = default; 90 | TypedArrayBase &operator=(TypedArrayBase &&) = default; 91 | 92 | TypedArrayKind getKind(jsi::Runtime &runtime) const; 93 | 94 | template 95 | TypedArray get(jsi::Runtime &runtime) const &; 96 | template 97 | TypedArray get(jsi::Runtime &runtime) &&; 98 | template 99 | TypedArray as(jsi::Runtime &runtime) const &; 100 | template 101 | TypedArray as(jsi::Runtime &runtime) &&; 102 | 103 | size_t size(jsi::Runtime &runtime) const; 104 | size_t length(jsi::Runtime &runtime) const; 105 | size_t byteLength(jsi::Runtime &runtime) const; 106 | size_t byteOffset(jsi::Runtime &runtime) const; 107 | bool hasBuffer(jsi::Runtime &runtime) const; 108 | 109 | std::vector toVector(jsi::Runtime &runtime); 110 | jsi::ArrayBuffer getBuffer(jsi::Runtime &runtime) const; 111 | 112 | private: 113 | template 114 | friend class TypedArray; 115 | }; 116 | 117 | bool isTypedArray(jsi::Runtime &runtime, const jsi::Object &jsObj); 118 | TypedArrayBase getTypedArray(jsi::Runtime &runtime, const jsi::Object &jsObj); 119 | 120 | std::vector arrayBufferToVector(jsi::Runtime &runtime, jsi::Object &jsObj); 121 | void arrayBufferUpdate( 122 | jsi::Runtime &runtime, 123 | jsi::ArrayBuffer &buffer, 124 | std::vector data, 125 | size_t offset); 126 | 127 | template 128 | class TypedArray : public TypedArrayBase 129 | { 130 | public: 131 | TypedArray(jsi::Runtime &runtime, size_t size); 132 | TypedArray(jsi::Runtime &runtime, std::vector> data); 133 | TypedArray(TypedArrayBase &&base); 134 | TypedArray(TypedArray &&) = default; 135 | TypedArray &operator=(TypedArray &&) = default; 136 | 137 | std::vector> toVector(jsi::Runtime &runtime); 138 | void update(jsi::Runtime &runtime, const std::vector> &data); 139 | }; 140 | 141 | template 142 | TypedArray TypedArrayBase::get(jsi::Runtime &runtime) const & 143 | { 144 | assert(getKind(runtime) == T); 145 | (void)runtime; // when assert is disabled we need to mark this as used 146 | return TypedArray(jsi::Value(runtime, jsi::Value(runtime, *this).asObject(runtime))); 147 | } 148 | 149 | template 150 | TypedArray TypedArrayBase::get(jsi::Runtime &runtime) && 151 | { 152 | assert(getKind(runtime) == T); 153 | (void)runtime; // when assert is disabled we need to mark this as used 154 | return TypedArray(std::move(*this)); 155 | } 156 | 157 | template 158 | TypedArray TypedArrayBase::as(jsi::Runtime &runtime) const & 159 | { 160 | if (getKind(runtime) != T) 161 | { 162 | throw jsi::JSError(runtime, "Object is not a TypedArray"); 163 | } 164 | return get(runtime); 165 | } 166 | 167 | template 168 | TypedArray TypedArrayBase::as(jsi::Runtime &runtime) && 169 | { 170 | if (getKind(runtime) != T) 171 | { 172 | throw jsi::JSError(runtime, "Object is not a TypedArray"); 173 | } 174 | return std::move(*this).get(runtime); 175 | } 176 | -------------------------------------------------------------------------------- /cpp/MGBigNumberHostObject.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Margelo 2 | #ifndef CPP_BigNumberHOSTOBJECT_H_ 3 | #define CPP_BigNumberHOSTOBJECT_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "MGDispatchQueue.h" 10 | #include "MGSmartHostObject.h" 11 | 12 | namespace margelo 13 | { 14 | 15 | namespace jsi = facebook::jsi; 16 | namespace react = facebook::react; 17 | 18 | class JSI_EXPORT MGBigNumberHostObject : public MGSmartHostObject 19 | { 20 | public: 21 | explicit MGBigNumberHostObject(std::shared_ptr jsCallInvoker, 22 | std::shared_ptr workerQueue); 23 | 24 | virtual ~MGBigNumberHostObject() 25 | { 26 | } 27 | 28 | static BN_CTX *bn_ctx; 29 | }; 30 | 31 | } // namespace margelo 32 | 33 | #endif // CPP_BigNumberHOSTOBJECT_H_ 34 | -------------------------------------------------------------------------------- /cpp/Utils/MGBigNumHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 16/03/2022. 3 | // 4 | 5 | #ifndef BIGNUMBEREXAMPLE_MGBIGNUMHELPER_H 6 | #define BIGNUMBEREXAMPLE_MGBIGNUMHELPER_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace margelo 17 | { 18 | 19 | class MGBigNumHelper 20 | { 21 | public: 22 | static void BN_xor(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); 23 | 24 | static void BN_and(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); 25 | 26 | static void BN_or(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); 27 | 28 | static void BN_notn(BIGNUM *pSt, unsigned int len); 29 | 30 | static void EGDC(BIGNUM *x, BIGNUM *y, BIGNUM *g, const BIGNUM *a, const BIGNUM *b); 31 | 32 | static void BN_smart_neg(BIGNUM *pSt); 33 | 34 | static std::string bn2Str(BIGNUM *num, int base, int len); 35 | 36 | static int charToInt(char &a); 37 | 38 | // static void bn_correct_top(BIGNUM *pSt); 39 | }; 40 | } // namespace margelo 41 | 42 | #endif // BIGNUMBEREXAMPLE_MGBIGNUMHELPER_H 43 | -------------------------------------------------------------------------------- /cpp/Utils/MGDispatchQueue.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 23/02/2022. 3 | // 4 | 5 | #include "MGDispatchQueue.h" 6 | 7 | namespace margelo 8 | { 9 | 10 | namespace DispatchQueue 11 | { 12 | 13 | dispatch_queue::dispatch_queue(std::string name, size_t thread_cnt) : name_{std::move(name)}, threads_(thread_cnt) 14 | { 15 | 16 | for (size_t i = 0; i < threads_.size(); i++) 17 | { 18 | threads_[i] = std::thread(&dispatch_queue::dispatch_thread_handler, this); 19 | } 20 | } 21 | 22 | dispatch_queue::~dispatch_queue() 23 | { 24 | 25 | // Signal to dispatch threads that it's time to wrap up 26 | std::unique_lock lock(lock_); 27 | quit_ = true; 28 | cv_.notify_all(); 29 | lock.unlock(); 30 | 31 | // Wait for threads to finish before we exit 32 | for (size_t i = 0; i < threads_.size(); i++) 33 | { 34 | if (threads_[i].joinable()) 35 | { 36 | threads_[i].join(); 37 | } 38 | } 39 | } 40 | 41 | void dispatch_queue::dispatch(const fp_t &op) 42 | { 43 | std::unique_lock lock(lock_); 44 | q_.push(op); 45 | cv_.notify_one(); 46 | } 47 | 48 | void dispatch_queue::dispatch(fp_t &&op) 49 | { 50 | std::unique_lock lock(lock_); 51 | q_.push(std::move(op)); 52 | cv_.notify_one(); 53 | } 54 | 55 | void dispatch_queue::dispatch_thread_handler(void) 56 | { 57 | std::unique_lock lock(lock_); 58 | 59 | do 60 | { 61 | // Wait until we have data or a quit signal 62 | cv_.wait(lock, [this] 63 | { return (q_.size() || quit_); }); 64 | 65 | // after wait, we own the lock 66 | if (!quit_ && q_.size()) 67 | { 68 | auto op = std::move(q_.front()); 69 | q_.pop(); 70 | 71 | // unlock now that we're done messing with the queue 72 | lock.unlock(); 73 | 74 | op(); 75 | 76 | lock.lock(); 77 | } 78 | } while (!quit_); 79 | } 80 | } // DispatchQueue namespace 81 | } // margelo namespace 82 | -------------------------------------------------------------------------------- /cpp/Utils/MGDispatchQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Szymon on 23/02/2022. 3 | // 4 | 5 | #ifndef BIGNUMBER_DISPATCHQUEUE_H 6 | #define BIGNUMBER_DISPATCHQUEUE_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace margelo 19 | { 20 | 21 | // taken from https://github.com/embeddedartistry/embedded-resources/blob/master/examples/cpp/dispatch.cpp 22 | namespace DispatchQueue 23 | { 24 | class dispatch_queue 25 | { 26 | typedef std::function fp_t; 27 | 28 | public: 29 | explicit dispatch_queue(std::string name, size_t thread_cnt = 1); 30 | ~dispatch_queue(); 31 | 32 | // dispatch and copy 33 | void dispatch(const fp_t &op); 34 | // dispatch and move 35 | void dispatch(fp_t &&op); 36 | 37 | // Deleted operations 38 | dispatch_queue(const dispatch_queue &rhs) = delete; 39 | dispatch_queue &operator=(const dispatch_queue &rhs) = delete; 40 | dispatch_queue(dispatch_queue &&rhs) = delete; 41 | dispatch_queue &operator=(dispatch_queue &&rhs) = delete; 42 | 43 | private: 44 | std::string name_; 45 | std::mutex lock_; 46 | std::vector threads_; 47 | std::queue q_; 48 | std::condition_variable cv_; 49 | bool quit_ = false; 50 | 51 | void dispatch_thread_handler(void); 52 | }; 53 | } // namespace DispatchQueue 54 | 55 | } // namespace margelo 56 | 57 | #endif // BIGNUMBER_DISPATCHQUEUE_H 58 | -------------------------------------------------------------------------------- /example/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | ios/.xcode.env.local 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | .cxx/ 34 | *.keystore 35 | !debug.keystore 36 | 37 | # node.js 38 | # 39 | node_modules/ 40 | npm-debug.log 41 | yarn-error.log 42 | 43 | # fastlane 44 | # 45 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 46 | # screenshots whenever they are needed. 47 | # For more information about the recommended setup visit: 48 | # https://docs.fastlane.tools/best-practices/source-control/ 49 | 50 | **/fastlane/report.xml 51 | **/fastlane/Preview.html 52 | **/fastlane/screenshots 53 | **/fastlane/test_output 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # Ruby / CocoaPods 59 | /ios/Pods/ 60 | /vendor/bundle/ 61 | 62 | # Temporary files created by Metro to check the health of the file watcher 63 | .metro-health-check* 64 | -------------------------------------------------------------------------------- /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /example/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby '>= 2.6.10' 5 | 6 | gem 'cocoapods', '>= 1.11.3' 7 | -------------------------------------------------------------------------------- /example/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.6) 5 | rexml 6 | activesupport (7.0.4.3) 7 | concurrent-ruby (~> 1.0, >= 1.0.2) 8 | i18n (>= 1.6, < 2) 9 | minitest (>= 5.1) 10 | tzinfo (~> 2.0) 11 | addressable (2.8.3) 12 | public_suffix (>= 2.0.2, < 6.0) 13 | algoliasearch (1.27.5) 14 | httpclient (~> 2.8, >= 2.8.3) 15 | json (>= 1.5.1) 16 | atomos (0.1.3) 17 | claide (1.1.0) 18 | cocoapods (1.12.0) 19 | addressable (~> 2.8) 20 | claide (>= 1.0.2, < 2.0) 21 | cocoapods-core (= 1.12.0) 22 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 23 | cocoapods-downloader (>= 1.6.0, < 2.0) 24 | cocoapods-plugins (>= 1.0.0, < 2.0) 25 | cocoapods-search (>= 1.0.0, < 2.0) 26 | cocoapods-trunk (>= 1.6.0, < 2.0) 27 | cocoapods-try (>= 1.1.0, < 2.0) 28 | colored2 (~> 3.1) 29 | escape (~> 0.0.4) 30 | fourflusher (>= 2.3.0, < 3.0) 31 | gh_inspector (~> 1.0) 32 | molinillo (~> 0.8.0) 33 | nap (~> 1.0) 34 | ruby-macho (>= 2.3.0, < 3.0) 35 | xcodeproj (>= 1.21.0, < 2.0) 36 | cocoapods-core (1.12.0) 37 | activesupport (>= 5.0, < 8) 38 | addressable (~> 2.8) 39 | algoliasearch (~> 1.0) 40 | concurrent-ruby (~> 1.1) 41 | fuzzy_match (~> 2.0.4) 42 | nap (~> 1.0) 43 | netrc (~> 0.11) 44 | public_suffix (~> 4.0) 45 | typhoeus (~> 1.0) 46 | cocoapods-deintegrate (1.0.5) 47 | cocoapods-downloader (1.6.3) 48 | cocoapods-plugins (1.0.0) 49 | nap 50 | cocoapods-search (1.0.1) 51 | cocoapods-trunk (1.6.0) 52 | nap (>= 0.8, < 2.0) 53 | netrc (~> 0.11) 54 | cocoapods-try (1.2.0) 55 | colored2 (3.1.2) 56 | concurrent-ruby (1.2.2) 57 | escape (0.0.4) 58 | ethon (0.16.0) 59 | ffi (>= 1.15.0) 60 | ffi (1.15.5) 61 | fourflusher (2.3.1) 62 | fuzzy_match (2.0.4) 63 | gh_inspector (1.1.3) 64 | httpclient (2.8.3) 65 | i18n (1.12.0) 66 | concurrent-ruby (~> 1.0) 67 | json (2.6.3) 68 | minitest (5.18.0) 69 | molinillo (0.8.0) 70 | nanaimo (0.3.0) 71 | nap (1.1.0) 72 | netrc (0.11.0) 73 | public_suffix (4.0.7) 74 | rexml (3.2.5) 75 | ruby-macho (2.5.1) 76 | typhoeus (1.4.0) 77 | ethon (>= 0.9.0) 78 | tzinfo (2.0.6) 79 | concurrent-ruby (~> 1.0) 80 | xcodeproj (1.22.0) 81 | CFPropertyList (>= 2.3.3, < 4.0) 82 | atomos (~> 0.1.3) 83 | claide (>= 1.0.2, < 2.0) 84 | colored2 (~> 3.1) 85 | nanaimo (~> 0.3.0) 86 | rexml (~> 3.2.4) 87 | 88 | PLATFORMS 89 | ruby 90 | 91 | DEPENDENCIES 92 | cocoapods (>= 1.11.3) 93 | 94 | RUBY VERSION 95 | ruby 2.7.6p219 96 | 97 | BUNDLED WITH 98 | 2.1.4 99 | -------------------------------------------------------------------------------- /example/__tests__/App-test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /example/_node-version: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/example/android/app/debug.keystore -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/android/app/src/debug/java/com/bignumberexample/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.bignumberexample; 8 | 9 | import android.content.Context; 10 | import com.facebook.flipper.android.AndroidFlipperClient; 11 | import com.facebook.flipper.android.utils.FlipperUtils; 12 | import com.facebook.flipper.core.FlipperClient; 13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; 14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; 15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; 16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping; 17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; 18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; 19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; 20 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; 21 | import com.facebook.react.ReactInstanceEventListener; 22 | import com.facebook.react.ReactInstanceManager; 23 | import com.facebook.react.bridge.ReactContext; 24 | import com.facebook.react.modules.network.NetworkingModule; 25 | import okhttp3.OkHttpClient; 26 | 27 | /** 28 | * Class responsible of loading Flipper inside your React Native application. This is the debug 29 | * flavor of it. Here you can add your own plugins and customize the Flipper setup. 30 | */ 31 | public class ReactNativeFlipper { 32 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 33 | if (FlipperUtils.shouldEnableFlipper(context)) { 34 | final FlipperClient client = AndroidFlipperClient.getInstance(context); 35 | 36 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); 37 | client.addPlugin(new DatabasesFlipperPlugin(context)); 38 | client.addPlugin(new SharedPreferencesFlipperPlugin(context)); 39 | client.addPlugin(CrashReporterPlugin.getInstance()); 40 | 41 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); 42 | NetworkingModule.setCustomClientBuilder( 43 | new NetworkingModule.CustomClientBuilder() { 44 | @Override 45 | public void apply(OkHttpClient.Builder builder) { 46 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); 47 | } 48 | }); 49 | client.addPlugin(networkFlipperPlugin); 50 | client.start(); 51 | 52 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized 53 | // Hence we run if after all native modules have been initialized 54 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); 55 | if (reactContext == null) { 56 | reactInstanceManager.addReactInstanceEventListener( 57 | new ReactInstanceEventListener() { 58 | @Override 59 | public void onReactContextInitialized(ReactContext reactContext) { 60 | reactInstanceManager.removeReactInstanceEventListener(this); 61 | reactContext.runOnNativeModulesQueueThread( 62 | new Runnable() { 63 | @Override 64 | public void run() { 65 | client.addPlugin(new FrescoFlipperPlugin()); 66 | } 67 | }); 68 | } 69 | }); 70 | } else { 71 | client.addPlugin(new FrescoFlipperPlugin()); 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/bignumberexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.bignumberexample; 2 | 3 | import com.facebook.react.ReactActivity; 4 | import com.facebook.react.ReactActivityDelegate; 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate; 7 | 8 | public class MainActivity extends ReactActivity { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | @Override 15 | protected String getMainComponentName() { 16 | return "BigNumberExample"; 17 | } 18 | 19 | /** 20 | * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link 21 | * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React 22 | * (aka React 18) with two boolean flags. 23 | */ 24 | @Override 25 | protected ReactActivityDelegate createReactActivityDelegate() { 26 | return new DefaultReactActivityDelegate( 27 | this, 28 | getMainComponentName(), 29 | // If you opted-in for the New Architecture, we enable the Fabric Renderer. 30 | DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled 31 | // If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18). 32 | DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/bignumberexample/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.bignumberexample; 2 | 3 | import android.app.Application; 4 | import com.facebook.react.PackageList; 5 | import com.facebook.react.ReactApplication; 6 | import com.facebook.react.ReactNativeHost; 7 | import com.facebook.react.ReactPackage; 8 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; 9 | import com.facebook.react.defaults.DefaultReactNativeHost; 10 | import com.facebook.soloader.SoLoader; 11 | import com.margelo.bignumber.BigNumberPackage; 12 | import java.util.List; 13 | 14 | public class MainApplication extends Application implements ReactApplication { 15 | 16 | private final ReactNativeHost mReactNativeHost = new DefaultReactNativeHost(this) { 17 | @Override 18 | public boolean getUseDeveloperSupport() { 19 | return BuildConfig.DEBUG; 20 | } 21 | 22 | @Override 23 | protected List getPackages() { 24 | @SuppressWarnings("UnnecessaryLocalVariable") 25 | List packages = new PackageList(this).getPackages(); 26 | // Packages that cannot be autolinked yet can be added manually here, for 27 | // example: 28 | // packages.add(new MyReactNativePackage()); 29 | packages.add(new BigNumberPackage()); 30 | return packages; 31 | } 32 | 33 | @Override 34 | protected String getJSMainModuleName() { 35 | return "index"; 36 | } 37 | 38 | @Override 39 | protected boolean isNewArchEnabled() { 40 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; 41 | } 42 | 43 | @Override 44 | protected Boolean isHermesEnabled() { 45 | return BuildConfig.IS_HERMES_ENABLED; 46 | } 47 | }; 48 | 49 | @Override 50 | public ReactNativeHost getReactNativeHost() { 51 | return mReactNativeHost; 52 | } 53 | 54 | @Override 55 | public void onCreate() { 56 | super.onCreate(); 57 | SoLoader.init(this, /* native exopackage */ false); 58 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 59 | // If you opted-in for the New Architecture, we load the native entry point for 60 | // this app. 61 | DefaultNewArchitectureEntryPoint.load(); 62 | } 63 | ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 21 | 22 | 23 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | BigNumberExample 3 | 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/android/app/src/release/java/com/bignumberexample/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.bignumberexample; 8 | 9 | import android.content.Context; 10 | import com.facebook.react.ReactInstanceManager; 11 | 12 | /** 13 | * Class responsible of loading Flipper inside your React Native application. This is the release 14 | * flavor of it so it's empty as we don't want to load Flipper. 15 | */ 16 | public class ReactNativeFlipper { 17 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 18 | // Do nothing as we don't want to initialize Flipper on Release. 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "33.0.0" 6 | minSdkVersion = 21 7 | compileSdkVersion = 33 8 | targetSdkVersion = 33 9 | 10 | // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. 11 | ndkVersion = "23.1.7779620" 12 | } 13 | repositories { 14 | google() 15 | mavenCentral() 16 | } 17 | dependencies { 18 | classpath("com.android.tools.build:gradle:7.3.1") 19 | classpath("com.facebook.react:react-native-gradle-plugin") 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Version of flipper SDK to use with React Native 28 | FLIPPER_VERSION=0.125.0 29 | 30 | # Use this property to specify which architecture you want to build. 31 | # You can also override it from the CLI using 32 | # ./gradlew -PreactNativeArchitectures=x86_64 33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 34 | 35 | # Use this property to enable support to the new architecture. 36 | # This will allow you to use TurboModules and the Fabric render in 37 | # your application. You should enable this flag either if you want 38 | # to write custom TurboModules/Fabric components OR use libraries that 39 | # are providing them. 40 | newArchEnabled=false 41 | 42 | # Use this property to enable or disable the Hermes JS engine. 43 | # If set to false, you will be using JSC instead. 44 | hermesEnabled=true 45 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margelo/react-native-bignumber/075748232aa3753da375180338abb4daf309706e/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'BigNumberExample' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | includeBuild('../node_modules/react-native-gradle-plugin') 5 | 6 | include ':react-native-bignumber' 7 | project(':react-native-bignumber').projectDir = new File(rootProject.projectDir, '../../android') -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BigNumberExample", 3 | "displayName": "BigNumber Example" 4 | } -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const pak = require('../package.json'); 3 | 4 | module.exports = { 5 | presets: ['module:metro-react-native-babel-preset'], 6 | plugins: [ 7 | [ 8 | 'module-resolver', 9 | { 10 | extensions: ['.js', '.ts', '.json', '.jsx', '.tsx'], 11 | alias: { 12 | [pak.name]: path.join(__dirname, '..', pak.source), 13 | bn_elliptic: path.join(__dirname, 'src', 'bn-elliptic', 'lib'), 14 | stream: 'stream-browserify', 15 | "buffer":"@craftzdog/react-native-buffer" 16 | }, 17 | }, 18 | ], 19 | ], 20 | }; 21 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | import { Buffer } from 'buffer'; 2 | global.Buffer = Buffer; 3 | global.process = { 4 | cwd: () => 'sxsx', 5 | env: { NODE_ENV: 'production' }, 6 | }; 7 | global.location = {}; 8 | 9 | import { AppRegistry } from 'react-native'; 10 | import App from './src/App'; 11 | import { name as appName } from './app.json'; 12 | 13 | AppRegistry.registerComponent(appName, () => App); 14 | -------------------------------------------------------------------------------- /example/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | export NODE_BINARY=$(command -v node) 2 | -------------------------------------------------------------------------------- /example/ios/BigNumberExample.xcodeproj/xcshareddata/xcschemes/BigNumberExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /example/ios/BigNumberExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/BigNumberExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/BigNumberExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : RCTAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/ios/BigNumberExample/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | 5 | @implementation AppDelegate 6 | 7 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 8 | { 9 | self.moduleName = @"BigNumberExample"; 10 | // You can add your custom initial props in the dictionary below. 11 | // They will be passed down to the ViewController used by React Native. 12 | self.initialProps = @{}; 13 | 14 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 15 | } 16 | 17 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 18 | { 19 | #if DEBUG 20 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 21 | #else 22 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 23 | #endif 24 | } 25 | 26 | /// This method controls whether the `concurrentRoot`feature of React18 is turned on or off. 27 | /// 28 | /// @see: https://reactjs.org/blog/2022/03/29/react-v18.html 29 | /// @note: This requires to be rendering on Fabric (i.e. on the New Architecture). 30 | /// @return: `true` if the `concurrentRoot` feature is enabled. Otherwise, it returns `false`. 31 | - (BOOL)concurrentRootEnabled 32 | { 33 | return true; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /example/ios/BigNumberExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /example/ios/BigNumberExample/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/BigNumberExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | BigNumberExample 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(CURRENT_PROJECT_VERSION) 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSExceptionDomains 30 | 31 | localhost 32 | 33 | NSExceptionAllowsInsecureHTTPLoads 34 | 35 | 36 | 37 | 38 | NSLocationWhenInUseUsageDescription 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UIViewControllerBasedStatusBarAppearance 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /example/ios/BigNumberExample/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /example/ios/BigNumberExample/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /example/ios/BigNumberExampleTests/BigNumberExampleTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface BigNumberExampleTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation BigNumberExampleTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction( 38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 39 | if (level >= RCTLogLevelError) { 40 | redboxError = message; 41 | } 42 | }); 43 | #endif 44 | 45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 48 | 49 | foundElement = [self findSubviewInView:vc.view 50 | matching:^BOOL(UIView *view) { 51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 52 | return YES; 53 | } 54 | return NO; 55 | }]; 56 | } 57 | 58 | #ifdef DEBUG 59 | RCTSetLogFunction(RCTDefaultLogFunction); 60 | #endif 61 | 62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /example/ios/BigNumberExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../node_modules/react-native/scripts/react_native_pods' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | platform :ios, min_ios_version_supported 5 | prepare_react_native_project! 6 | 7 | # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. 8 | # because `react-native-flipper` depends on (FlipperKit,...) that will be excluded 9 | # 10 | # To fix this you can also exclude `react-native-flipper` using a `react-native.config.js` 11 | # ```js 12 | # module.exports = { 13 | # dependencies: { 14 | # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), 15 | # ``` 16 | flipper_config = FlipperConfiguration.disabled 17 | 18 | linkage = ENV['USE_FRAMEWORKS'] 19 | if linkage != nil 20 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green 21 | use_frameworks! :linkage => linkage.to_sym 22 | end 23 | 24 | target 'BigNumberExample' do 25 | config = use_native_modules! 26 | 27 | # Flags change depending on the env values. 28 | flags = get_default_flags() 29 | 30 | use_react_native!( 31 | :path => config[:reactNativePath], 32 | # Hermes is now enabled by default. Disable by setting this flag to false. 33 | # Upcoming versions of React Native may rely on get_default_flags(), but 34 | # we make it explicit here to aid in the React Native upgrade process. 35 | :hermes_enabled => flags[:hermes_enabled], 36 | :fabric_enabled => flags[:fabric_enabled], 37 | # Enables Flipper. 38 | # 39 | # Note that if you have use_frameworks! enabled, Flipper will not work and 40 | # you should disable the next line. 41 | :flipper_configuration => flipper_config, 42 | # An absolute path to your application root. 43 | :app_path => "#{Pod::Config.instance.installation_root}/.." 44 | ) 45 | 46 | pod 'react-native-bignumber', :path => '../..' 47 | 48 | target 'BigNumberExampleTests' do 49 | inherit! :complete 50 | # Pods for testing 51 | end 52 | 53 | post_install do |installer| 54 | react_native_post_install( 55 | installer, 56 | # Set `mac_catalyst_enabled` to `true` in order to apply patches 57 | # necessary for Mac Catalyst builds 58 | :mac_catalyst_enabled => false 59 | ) 60 | __apply_Xcode_12_5_M1_post_install_workaround(installer) 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /example/ios/_xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /example/metro.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const blacklist = require('metro-config/src/defaults/exclusionList'); 3 | const escape = require('escape-string-regexp'); 4 | const pak = require('../package.json'); 5 | 6 | const root = path.resolve(__dirname, '..'); 7 | 8 | const modules = Object.keys({ 9 | ...pak.peerDependencies, 10 | }); 11 | 12 | module.exports = { 13 | projectRoot: __dirname, 14 | watchFolders: [root], 15 | 16 | // We need to make sure that only one version is loaded for peerDependencies 17 | // So we blacklist them at the root, and alias them to the versions in example's node_modules 18 | resolver: { 19 | blacklistRE: blacklist( 20 | modules.map( 21 | (m) => 22 | new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`) 23 | ) 24 | ), 25 | 26 | extraNodeModules: modules.reduce((acc, name) => { 27 | acc[name] = path.join(__dirname, 'node_modules', name); 28 | return acc; 29 | }, {}), 30 | }, 31 | 32 | transformer: { 33 | getTransformOptions: async () => ({ 34 | transform: { 35 | experimentalImportSupport: true, 36 | inlineRequires: true, 37 | }, 38 | }), 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bignumberexample", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "lint": "eslint .", 9 | "start": "react-native start", 10 | "test": "jest", 11 | "pods": "cd ios && bundle install && bundle exec pod install && cd ..", 12 | "postinstall": "patch-package" 13 | }, 14 | "dependencies": { 15 | "@craftzdog/react-native-buffer": "^6.0.5", 16 | "@react-native-community/checkbox": "^0.5.15", 17 | "@react-navigation/native": "^6.1.6", 18 | "@react-navigation/native-stack": "^6.9.12", 19 | "Buffer": "^0.0.0", 20 | "bn.js": "^5.2.1", 21 | "chai": "^4.3.7", 22 | "elliptic": "^6.5.4", 23 | "events": "^3.3.0", 24 | "mocha": "^10.2.0", 25 | "react": "18.2.0", 26 | "react-native": "0.71.6", 27 | "react-native-quick-base64": "^2.0.5", 28 | "react-native-safe-area-context": "^4.5.0", 29 | "react-native-screens": "^3.20.0", 30 | "stream-browserify": "^3.0.0", 31 | "util": "^0.12.5" 32 | }, 33 | "devDependencies": { 34 | "@babel/core": "^7.20.0", 35 | "@babel/preset-env": "^7.20.0", 36 | "@babel/runtime": "^7.20.0", 37 | "@react-native-community/eslint-config": "^3.2.0", 38 | "@tsconfig/react-native": "^2.0.2", 39 | "@types/chai": "^4.3.4", 40 | "@types/elliptic": "^6.4.14", 41 | "@types/jest": "^29.2.1", 42 | "@types/mocha": "^10.0.1", 43 | "@types/react": "^18.0.24", 44 | "@types/react-test-renderer": "^18.0.0", 45 | "babel-jest": "^29.2.1", 46 | "babel-plugin-module-resolver": "^5.0.0", 47 | "eslint": "^8.19.0", 48 | "jest": "^29.2.1", 49 | "metro-react-native-babel-preset": "0.73.9", 50 | "patch-package": "^6.5.1", 51 | "prettier": "^2.4.1", 52 | "react-test-renderer": "18.2.0", 53 | "typescript": "4.8.4" 54 | }, 55 | "jest": { 56 | "preset": "react-native" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /example/patches/elliptic+6.5.4.patch: -------------------------------------------------------------------------------- 1 | diff --git a/node_modules/elliptic/lib/elliptic/curve/base.js b/node_modules/elliptic/lib/elliptic/curve/base.js 2 | index 8543fa8..3bb90c6 100644 3 | --- a/node_modules/elliptic/lib/elliptic/curve/base.js 4 | +++ b/node_modules/elliptic/lib/elliptic/curve/base.js 5 | @@ -1,6 +1,6 @@ 6 | 'use strict'; 7 | 8 | -var BN = require('bn.js'); 9 | +var BN = require('react-native-bignumber'); 10 | var utils = require('../utils'); 11 | var getNAF = utils.getNAF; 12 | var getJSF = utils.getJSF; 13 | diff --git a/node_modules/elliptic/lib/elliptic/curve/edwards.js b/node_modules/elliptic/lib/elliptic/curve/edwards.js 14 | index 6e757c6..94e3662 100644 15 | --- a/node_modules/elliptic/lib/elliptic/curve/edwards.js 16 | +++ b/node_modules/elliptic/lib/elliptic/curve/edwards.js 17 | @@ -1,7 +1,7 @@ 18 | 'use strict'; 19 | 20 | var utils = require('../utils'); 21 | -var BN = require('bn.js'); 22 | +var BN = require('react-native-bignumber'); 23 | var inherits = require('inherits'); 24 | var Base = require('./base'); 25 | 26 | diff --git a/node_modules/elliptic/lib/elliptic/curve/mont.js b/node_modules/elliptic/lib/elliptic/curve/mont.js 27 | index 4b9f80f..31aba54 100644 28 | --- a/node_modules/elliptic/lib/elliptic/curve/mont.js 29 | +++ b/node_modules/elliptic/lib/elliptic/curve/mont.js 30 | @@ -1,6 +1,6 @@ 31 | 'use strict'; 32 | 33 | -var BN = require('bn.js'); 34 | +var BN = require('react-native-bignumber'); 35 | var inherits = require('inherits'); 36 | var Base = require('./base'); 37 | 38 | diff --git a/node_modules/elliptic/lib/elliptic/curve/short.js b/node_modules/elliptic/lib/elliptic/curve/short.js 39 | index eec36ec..c716766 100644 40 | --- a/node_modules/elliptic/lib/elliptic/curve/short.js 41 | +++ b/node_modules/elliptic/lib/elliptic/curve/short.js 42 | @@ -1,7 +1,7 @@ 43 | 'use strict'; 44 | 45 | var utils = require('../utils'); 46 | -var BN = require('bn.js'); 47 | +var BN = require('react-native-bignumber'); 48 | var inherits = require('inherits'); 49 | var Base = require('./base'); 50 | 51 | diff --git a/node_modules/elliptic/lib/elliptic/ec/index.js b/node_modules/elliptic/lib/elliptic/ec/index.js 52 | index 8b58781..199b79f 100644 53 | --- a/node_modules/elliptic/lib/elliptic/ec/index.js 54 | +++ b/node_modules/elliptic/lib/elliptic/ec/index.js 55 | @@ -1,6 +1,6 @@ 56 | 'use strict'; 57 | 58 | -var BN = require('bn.js'); 59 | +var BN = require('react-native-bignumber'); 60 | var HmacDRBG = require('hmac-drbg'); 61 | var utils = require('../utils'); 62 | var curves = require('../curves'); 63 | diff --git a/node_modules/elliptic/lib/elliptic/ec/key.js b/node_modules/elliptic/lib/elliptic/ec/key.js 64 | index 55bf299..fd245ec 100644 65 | --- a/node_modules/elliptic/lib/elliptic/ec/key.js 66 | +++ b/node_modules/elliptic/lib/elliptic/ec/key.js 67 | @@ -1,6 +1,6 @@ 68 | 'use strict'; 69 | 70 | -var BN = require('bn.js'); 71 | +var BN = require('react-native-bignumber'); 72 | var utils = require('../utils'); 73 | var assert = utils.assert; 74 | 75 | diff --git a/node_modules/elliptic/lib/elliptic/ec/signature.js b/node_modules/elliptic/lib/elliptic/ec/signature.js 76 | index 539df6a..d23f9d6 100644 77 | --- a/node_modules/elliptic/lib/elliptic/ec/signature.js 78 | +++ b/node_modules/elliptic/lib/elliptic/ec/signature.js 79 | @@ -1,6 +1,6 @@ 80 | 'use strict'; 81 | 82 | -var BN = require('bn.js'); 83 | +var BN = require('react-native-bignumber'); 84 | 85 | var utils = require('../utils'); 86 | var assert = utils.assert; 87 | diff --git a/node_modules/elliptic/lib/elliptic/eddsa/signature.js b/node_modules/elliptic/lib/elliptic/eddsa/signature.js 88 | index 30ebc92..b9d7efe 100644 89 | --- a/node_modules/elliptic/lib/elliptic/eddsa/signature.js 90 | +++ b/node_modules/elliptic/lib/elliptic/eddsa/signature.js 91 | @@ -1,6 +1,6 @@ 92 | 'use strict'; 93 | 94 | -var BN = require('bn.js'); 95 | +var BN = require('react-native-bignumber'); 96 | var utils = require('../utils'); 97 | var assert = utils.assert; 98 | var cachedProperty = utils.cachedProperty; 99 | diff --git a/node_modules/elliptic/lib/elliptic/utils.js b/node_modules/elliptic/lib/elliptic/utils.js 100 | index 627a9f1..39aa514 100644 101 | --- a/node_modules/elliptic/lib/elliptic/utils.js 102 | +++ b/node_modules/elliptic/lib/elliptic/utils.js 103 | @@ -1,7 +1,7 @@ 104 | 'use strict'; 105 | 106 | var utils = exports; 107 | -var BN = require('bn.js'); 108 | +var BN = require('react-native-bignumber'); 109 | var minAssert = require('minimalistic-assert'); 110 | var minUtils = require('minimalistic-crypto-utils'); 111 | 112 | -------------------------------------------------------------------------------- /example/src/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Root } from './navigators/Root'; 3 | 4 | export default function App() { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /example/src/Testing/MochaRNAdapter.ts: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import type * as MochaTypes from 'mocha'; 3 | 4 | export const rootSuite = new Mocha.Suite('') as MochaTypes.Suite; 5 | 6 | let mochaContext = rootSuite; 7 | let only = false; 8 | 9 | export const clearTests = () => { 10 | rootSuite.suites = []; 11 | rootSuite.tests = []; 12 | mochaContext = rootSuite; 13 | only = false; 14 | }; 15 | 16 | export const it = (name: string, f: () => void): void => { 17 | if (!only) { 18 | mochaContext.addTest(new Mocha.Test(name, f) as MochaTypes.Test); 19 | } 20 | }; 21 | 22 | export const itOnly = (name: string, f: () => void): void => { 23 | clearTests(); 24 | mochaContext.addTest(new Mocha.Test(name, f) as MochaTypes.Test); 25 | only = true; 26 | }; 27 | 28 | export const describe = (name: string, f: () => void): void => { 29 | const prevMochaContext = mochaContext; 30 | mochaContext = new Mocha.Suite( 31 | name, 32 | prevMochaContext.ctx 33 | ) as MochaTypes.Suite; 34 | prevMochaContext.addSuite(mochaContext); 35 | f(); 36 | mochaContext = prevMochaContext; 37 | }; 38 | -------------------------------------------------------------------------------- /example/src/Testing/MochaSetup.ts: -------------------------------------------------------------------------------- 1 | import type { RowItemType } from '../navigators/children/TestingScreen/RowItemType'; 2 | import { rootSuite, clearTests } from './MochaRNAdapter'; 3 | import 'mocha'; 4 | import type * as MochaTypes from 'mocha'; 5 | 6 | export function testLib( 7 | addTestResult: (testResult: RowItemType) => void, 8 | testRegistrators: Array<() => void> = [] 9 | ) { 10 | console.log('setting up mocha'); 11 | 12 | const { 13 | EVENT_RUN_BEGIN, 14 | EVENT_RUN_END, 15 | EVENT_TEST_FAIL, 16 | EVENT_TEST_PASS, 17 | EVENT_SUITE_BEGIN, 18 | EVENT_SUITE_END, 19 | } = Mocha.Runner.constants; 20 | 21 | clearTests(); 22 | var runner = new Mocha.Runner(rootSuite) as MochaTypes.Runner; 23 | 24 | let indents = -1; 25 | const indent = () => Array(indents).join(' '); 26 | runner 27 | .once(EVENT_RUN_BEGIN, () => {}) 28 | .on(EVENT_SUITE_BEGIN, (suite: MochaTypes.Suite) => { 29 | const name = suite.fullTitle(); 30 | if (name !== '') { 31 | addTestResult({ 32 | indentation: indents, 33 | description: name, 34 | key: Math.random().toString(), 35 | type: 'grouping', 36 | }); 37 | } 38 | indents++; 39 | }) 40 | .on(EVENT_SUITE_END, () => { 41 | indents--; 42 | }) 43 | .on(EVENT_TEST_PASS, (test: MochaTypes.Runnable) => { 44 | addTestResult({ 45 | indentation: indents, 46 | description: test.fullTitle(), 47 | key: Math.random().toString(), 48 | type: 'correct', 49 | }); 50 | console.log(`${indent()}pass: ${test.fullTitle()}`); 51 | }) 52 | .on(EVENT_TEST_FAIL, (test: MochaTypes.Runnable, err: Error) => { 53 | addTestResult({ 54 | indentation: indents, 55 | description: test.fullTitle(), 56 | key: Math.random().toString(), 57 | type: 'incorrect', 58 | errorMsg: err.message, 59 | }); 60 | console.log( 61 | `${indent()}fail: ${test.fullTitle()} - error: ${err.message}` 62 | ); 63 | }) 64 | .once(EVENT_RUN_END, () => {}); 65 | 66 | testRegistrators.forEach((register) => { 67 | register(); 68 | }); 69 | 70 | runner.run(); 71 | 72 | return () => { 73 | console.log('aborting'); 74 | runner.abort(); 75 | }; 76 | } 77 | -------------------------------------------------------------------------------- /example/src/Testing/TestList.ts: -------------------------------------------------------------------------------- 1 | import type { TestItemType } from '../navigators/children/Entry/TestItemType'; 2 | import { registerArythmeticTests } from './bn-tests/arithmetic-test'; 3 | import { registerBinaryTests } from './bn-tests/binary-test'; 4 | import { registerRedTests } from './bn-tests/res-test'; 5 | import { registerConstructorTests } from './bn-tests/constructor-test'; 6 | import { registerUtilsTests } from './bn-tests/utils-test'; 7 | import { registerCurvedTests } from './elliptic-tests/curves'; 8 | import BN from 'react-native-bignumber'; 9 | import { describe, it } from './MochaRNAdapter'; 10 | import chai from 'chai'; 11 | 12 | export const TEST_LIST: Array = [ 13 | { 14 | description: 'SimpleTests', 15 | value: false, 16 | registrator: () => { 17 | describe('basic tests', () => { 18 | it('basic constructor and to String', () => { 19 | var a = new BN('10', 10); 20 | chai.expect(a.toString(10)).to.be.eql('10'); 21 | }); 22 | 23 | it('basic add', () => { 24 | var a = new BN('dead', 16); 25 | var b = new BN('101010', 2); 26 | 27 | var res = a.add(b); 28 | chai.expect(res.toString(10)).to.be.eql('57047'); 29 | }); 30 | 31 | it('basic add with negative num', () => { 32 | var a = new BN('5', 16); 33 | var b = new BN('-101010', 2); 34 | 35 | var res = a.add(b); 36 | chai.expect(res.toString(10)).to.be.eql('-37'); 37 | }); 38 | 39 | it('basic toArray', () => { 40 | chai.assert.deepEqual( 41 | new BN([1, 2, 3, 4], 'hex', 'le').toArray('le', 3), 42 | [1, 2, 3] 43 | ); 44 | }); 45 | }); 46 | }, 47 | }, 48 | { 49 | description: 'Arithmetic tests', 50 | value: false, 51 | registrator: registerArythmeticTests, 52 | }, 53 | { 54 | description: 'Binary tests', 55 | value: false, 56 | registrator: registerBinaryTests, 57 | }, 58 | { 59 | description: 'Mod tests', 60 | value: false, 61 | registrator: registerRedTests, 62 | }, 63 | { 64 | description: 'Constructor tests', 65 | value: false, 66 | registrator: registerConstructorTests, 67 | }, 68 | { 69 | description: 'Utils tests', 70 | value: false, 71 | registrator: registerUtilsTests, 72 | }, 73 | { 74 | description: 'Curves tests', 75 | value: false, 76 | registrator: registerCurvedTests, 77 | }, 78 | ]; 79 | -------------------------------------------------------------------------------- /example/src/Testing/bn-tests/README.md: -------------------------------------------------------------------------------- 1 | # All of the test has been copied from https://github.com/indutny/bn.js/blob/master/test/utils-test.js -------------------------------------------------------------------------------- /example/src/Testing/bn-tests/pummel/dh-group-test.js: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | 3 | var assert = require('assert').strict; 4 | var BN = require('../../').BN; 5 | var fixtures = require('../fixtures'); 6 | 7 | describe('BN.js/Slow DH test', function () { 8 | var groups = fixtures.dhGroups; 9 | Object.keys(groups).forEach(function (name) { 10 | it('should match public key for ' + name + ' group', function () { 11 | var group = groups[name]; 12 | 13 | this.timeout(3600 * 1000); 14 | 15 | var base = new BN(2); 16 | var mont = BN.red(new BN(group.prime, 16)); 17 | var priv = new BN(group.priv, 16); 18 | var multed = base.toRed(mont).redPow(priv).fromRed(); 19 | var actual = Buffer.from(multed.toArray()); 20 | assert.equal(actual.toString('hex'), group.pub); 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /example/src/bn-elliptic/lib/elliptic/curve/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var curve = exports; 4 | 5 | curve.base = require('./base'); 6 | curve.short = require('./short'); 7 | curve.mont = require('./mont'); 8 | curve.edwards = require('./edwards'); 9 | -------------------------------------------------------------------------------- /example/src/bn-elliptic/lib/elliptic/curve/mont.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var BN = require('bn.js'); 4 | var inherits = require('inherits'); 5 | var Base = require('./base'); 6 | 7 | var utils = require('../utils'); 8 | 9 | function MontCurve(conf) { 10 | Base.call(this, 'mont', conf); 11 | 12 | this.a = new BN(conf.a, 16).toRed(this.red); 13 | this.b = new BN(conf.b, 16).toRed(this.red); 14 | this.i4 = new BN(4).toRed(this.red).redInvm(); 15 | this.two = new BN(2).toRed(this.red); 16 | this.a24 = this.i4.redMul(this.a.redAdd(this.two)); 17 | } 18 | inherits(MontCurve, Base); 19 | module.exports = MontCurve; 20 | 21 | MontCurve.prototype.validate = function validate(point) { 22 | var x = point.normalize().x; 23 | var x2 = x.redSqr(); 24 | var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); 25 | var y = rhs.redSqrt(); 26 | 27 | return y.redSqr().cmp(rhs) === 0; 28 | }; 29 | 30 | function Point(curve, x, z) { 31 | Base.BasePoint.call(this, curve, 'projective'); 32 | if (x === null && z === null) { 33 | this.x = this.curve.one; 34 | this.z = this.curve.zero; 35 | } else { 36 | this.x = new BN(x, 16); 37 | this.z = new BN(z, 16); 38 | if (!this.x.red) this.x = this.x.toRed(this.curve.red); 39 | if (!this.z.red) this.z = this.z.toRed(this.curve.red); 40 | } 41 | } 42 | inherits(Point, Base.BasePoint); 43 | 44 | MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { 45 | return this.point(utils.toArray(bytes, enc), 1); 46 | }; 47 | 48 | MontCurve.prototype.point = function point(x, z) { 49 | return new Point(this, x, z); 50 | }; 51 | 52 | MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { 53 | return Point.fromJSON(this, obj); 54 | }; 55 | 56 | Point.prototype.precompute = function precompute() { 57 | // No-op 58 | }; 59 | 60 | Point.prototype._encode = function _encode() { 61 | return this.getX().toArray('be', this.curve.p.byteLength()); 62 | }; 63 | 64 | Point.fromJSON = function fromJSON(curve, obj) { 65 | return new Point(curve, obj[0], obj[1] || curve.one); 66 | }; 67 | 68 | Point.prototype.inspect = function inspect() { 69 | if (this.isInfinity()) return ''; 70 | return ( 71 | '' 76 | ); 77 | }; 78 | 79 | Point.prototype.isInfinity = function isInfinity() { 80 | // XXX This code assumes that zero is always zero in red 81 | return this.z.cmpn(0) === 0; 82 | }; 83 | 84 | Point.prototype.dbl = function dbl() { 85 | // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 86 | // 2M + 2S + 4A 87 | 88 | // A = X1 + Z1 89 | var a = this.x.redAdd(this.z); 90 | // AA = A^2 91 | var aa = a.redSqr(); 92 | // B = X1 - Z1 93 | var b = this.x.redSub(this.z); 94 | // BB = B^2 95 | var bb = b.redSqr(); 96 | // C = AA - BB 97 | var c = aa.redSub(bb); 98 | // X3 = AA * BB 99 | var nx = aa.redMul(bb); 100 | // Z3 = C * (BB + A24 * C) 101 | var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); 102 | return this.curve.point(nx, nz); 103 | }; 104 | 105 | Point.prototype.add = function add() { 106 | throw new Error('Not supported on Montgomery curve'); 107 | }; 108 | 109 | Point.prototype.diffAdd = function diffAdd(p, diff) { 110 | // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 111 | // 4M + 2S + 6A 112 | 113 | // A = X2 + Z2 114 | var a = this.x.redAdd(this.z); 115 | // B = X2 - Z2 116 | var b = this.x.redSub(this.z); 117 | // C = X3 + Z3 118 | var c = p.x.redAdd(p.z); 119 | // D = X3 - Z3 120 | var d = p.x.redSub(p.z); 121 | // DA = D * A 122 | var da = d.redMul(a); 123 | // CB = C * B 124 | var cb = c.redMul(b); 125 | // X5 = Z1 * (DA + CB)^2 126 | var nx = diff.z.redMul(da.redAdd(cb).redSqr()); 127 | // Z5 = X1 * (DA - CB)^2 128 | var nz = diff.x.redMul(da.redISub(cb).redSqr()); 129 | return this.curve.point(nx, nz); 130 | }; 131 | 132 | Point.prototype.mul = function mul(k) { 133 | var t = k.clone(); 134 | var a = this; // (N / 2) * Q + Q 135 | var b = this.curve.point(null, null); // (N / 2) * Q 136 | var c = this; // Q 137 | 138 | for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) bits.push(t.andln(1)); 139 | 140 | for (var i = bits.length - 1; i >= 0; i--) { 141 | if (bits[i] === 0) { 142 | // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q 143 | a = a.diffAdd(b, c); 144 | // N * Q = 2 * ((N / 2) * Q + Q)) 145 | b = b.dbl(); 146 | } else { 147 | // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) 148 | b = a.diffAdd(b, c); 149 | // N * Q + Q = 2 * ((N / 2) * Q + Q) 150 | a = a.dbl(); 151 | } 152 | } 153 | return b; 154 | }; 155 | 156 | Point.prototype.mulAdd = function mulAdd() { 157 | throw new Error('Not supported on Montgomery curve'); 158 | }; 159 | 160 | Point.prototype.jumlAdd = function jumlAdd() { 161 | throw new Error('Not supported on Montgomery curve'); 162 | }; 163 | 164 | Point.prototype.eq = function eq(other) { 165 | return this.getX().cmp(other.getX()) === 0; 166 | }; 167 | 168 | Point.prototype.normalize = function normalize() { 169 | this.x = this.x.redMul(this.z.redInvm()); 170 | this.z = this.curve.one; 171 | return this; 172 | }; 173 | 174 | Point.prototype.getX = function getX() { 175 | // Normalize coordinates 176 | this.normalize(); 177 | 178 | return this.x.fromRed(); 179 | }; 180 | -------------------------------------------------------------------------------- /example/src/bn-elliptic/lib/elliptic/curves.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var curves = exports; 4 | 5 | var hash = require('hash.js'); 6 | var curve = require('./curve'); 7 | var utils = require('./utils'); 8 | 9 | var assert = utils.assert; 10 | 11 | function PresetCurve(options) { 12 | if (options.type === 'short') this.curve = new curve.short(options); 13 | else if (options.type === 'edwards') this.curve = new curve.edwards(options); 14 | else this.curve = new curve.mont(options); 15 | this.g = this.curve.g; 16 | this.n = this.curve.n; 17 | this.hash = options.hash; 18 | 19 | assert(this.g.validate(), 'Invalid curve'); 20 | assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, G*N != O'); 21 | } 22 | curves.PresetCurve = PresetCurve; 23 | 24 | function defineCurve(name, options) { 25 | Object.defineProperty(curves, name, { 26 | configurable: true, 27 | enumerable: true, 28 | get: function () { 29 | var curve; 30 | try { 31 | curve = new PresetCurve(options); 32 | } catch (e) { 33 | throw name; 34 | } 35 | Object.defineProperty(curves, name, { 36 | configurable: true, 37 | enumerable: true, 38 | value: curve, 39 | }); 40 | return curve; 41 | }, 42 | }); 43 | } 44 | 45 | defineCurve('p192', { 46 | type: 'short', 47 | prime: 'p192', 48 | p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', 49 | a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', 50 | b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', 51 | n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', 52 | hash: hash.sha256, 53 | gRed: false, 54 | g: [ 55 | '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', 56 | '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811', 57 | ], 58 | }); 59 | 60 | defineCurve('p224', { 61 | type: 'short', 62 | prime: 'p224', 63 | p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', 64 | a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', 65 | b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', 66 | n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', 67 | hash: hash.sha256, 68 | gRed: false, 69 | g: [ 70 | 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', 71 | 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34', 72 | ], 73 | }); 74 | 75 | defineCurve('p256', { 76 | type: 'short', 77 | prime: null, 78 | p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', 79 | a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', 80 | b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', 81 | n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', 82 | hash: hash.sha256, 83 | gRed: false, 84 | g: [ 85 | '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', 86 | '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5', 87 | ], 88 | }); 89 | 90 | defineCurve('p384', { 91 | type: 'short', 92 | prime: null, 93 | p: 94 | 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + 95 | 'fffffffe ffffffff 00000000 00000000 ffffffff', 96 | a: 97 | 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + 98 | 'fffffffe ffffffff 00000000 00000000 fffffffc', 99 | b: 100 | 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + 101 | '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', 102 | n: 103 | 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + 104 | 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', 105 | hash: hash.sha384, 106 | gRed: false, 107 | g: [ 108 | 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + 109 | '5502f25d bf55296c 3a545e38 72760ab7', 110 | '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + 111 | '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f', 112 | ], 113 | }); 114 | 115 | defineCurve('p521', { 116 | type: 'short', 117 | prime: null, 118 | p: 119 | '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + 120 | 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + 121 | 'ffffffff ffffffff ffffffff ffffffff ffffffff', 122 | a: 123 | '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + 124 | 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + 125 | 'ffffffff ffffffff ffffffff ffffffff fffffffc', 126 | b: 127 | '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + 128 | '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + 129 | '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', 130 | n: 131 | '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + 132 | 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + 133 | 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', 134 | hash: hash.sha512, 135 | gRed: false, 136 | g: [ 137 | '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + 138 | '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + 139 | 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', 140 | '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + 141 | '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + 142 | '3fad0761 353c7086 a272c240 88be9476 9fd16650', 143 | ], 144 | }); 145 | 146 | defineCurve('curve25519', { 147 | type: 'mont', 148 | prime: 'p25519', 149 | p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', 150 | a: '76d06', 151 | b: '1', 152 | n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', 153 | hash: hash.sha256, 154 | gRed: false, 155 | g: ['9'], 156 | }); 157 | 158 | defineCurve('ed25519', { 159 | type: 'edwards', 160 | prime: 'p25519', 161 | p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', 162 | a: '-1', 163 | c: '1', 164 | // -121665 * (121666^(-1)) (mod P) 165 | d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', 166 | n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', 167 | hash: hash.sha256, 168 | gRed: false, 169 | g: [ 170 | '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', 171 | 172 | // 4/5 173 | '6666666666666666666666666666666666666666666666666666666666666658', 174 | ], 175 | }); 176 | 177 | var pre; 178 | try { 179 | pre = require('./precomputed/secp256k1'); 180 | } catch (e) { 181 | pre = undefined; 182 | } 183 | 184 | defineCurve('secp256k1', { 185 | type: 'short', 186 | prime: 'k256', 187 | p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', 188 | a: '0', 189 | b: '7', 190 | n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', 191 | h: '1', 192 | hash: hash.sha256, 193 | 194 | // Precomputed endomorphism 195 | beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', 196 | lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', 197 | basis: [ 198 | { 199 | a: '3086d221a7d46bcde86c90e49284eb15', 200 | b: '-e4437ed6010e88286f547fa90abfe4c3', 201 | }, 202 | { 203 | a: '114ca50f7a8e2f3f657c1108d9d44cfd8', 204 | b: '3086d221a7d46bcde86c90e49284eb15', 205 | }, 206 | ], 207 | 208 | gRed: false, 209 | g: [ 210 | '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 211 | '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 212 | pre, 213 | ], 214 | }); 215 | -------------------------------------------------------------------------------- /example/src/bn-elliptic/lib/elliptic/ec/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var BN = require('bn.js'); 4 | var HmacDRBG = require('hmac-drbg'); 5 | var utils = require('../utils'); 6 | var curves = require('../curves'); 7 | var rand = require('brorand'); 8 | var assert = utils.assert; 9 | 10 | var KeyPair = require('./key'); 11 | var Signature = require('./signature'); 12 | 13 | function EC(options) { 14 | if (!(this instanceof EC)) return new EC(options); 15 | 16 | // Shortcut `elliptic.ec(curve-name)` 17 | if (typeof options === 'string') { 18 | assert( 19 | Object.prototype.hasOwnProperty.call(curves, options), 20 | 'Unknown curve ' + options 21 | ); 22 | 23 | options = curves[options]; 24 | } 25 | 26 | // Shortcut for `elliptic.ec(elliptic.curves.curveName)` 27 | if (options instanceof curves.PresetCurve) options = { curve: options }; 28 | 29 | this.curve = options.curve.curve; 30 | this.n = this.curve.n; 31 | this.nh = this.n.ushrn(1); 32 | this.g = this.curve.g; 33 | 34 | // Point on curve 35 | this.g = options.curve.g; 36 | this.g.precompute(options.curve.n.bitLength() + 1); 37 | 38 | // Hash for function for DRBG 39 | this.hash = options.hash || options.curve.hash; 40 | } 41 | module.exports = EC; 42 | 43 | EC.prototype.keyPair = function keyPair(options) { 44 | return new KeyPair(this, options); 45 | }; 46 | 47 | EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { 48 | return KeyPair.fromPrivate(this, priv, enc); 49 | }; 50 | 51 | EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { 52 | return KeyPair.fromPublic(this, pub, enc); 53 | }; 54 | 55 | EC.prototype.genKeyPair = function genKeyPair(options) { 56 | if (!options) options = {}; 57 | 58 | // Instantiate Hmac_DRBG 59 | var drbg = new HmacDRBG({ 60 | hash: this.hash, 61 | pers: options.pers, 62 | persEnc: options.persEnc || 'utf8', 63 | entropy: options.entropy || rand(this.hash.hmacStrength), 64 | entropyEnc: (options.entropy && options.entropyEnc) || 'utf8', 65 | nonce: this.n.toArray(), 66 | }); 67 | 68 | var bytes = this.n.byteLength(); 69 | var ns2 = this.n.sub(new BN(2)); 70 | for (;;) { 71 | var priv = new BN(drbg.generate(bytes)); 72 | if (priv.cmp(ns2) > 0) continue; 73 | 74 | priv.iaddn(1); 75 | return this.keyFromPrivate(priv); 76 | } 77 | }; 78 | 79 | EC.prototype._truncateToN = function _truncateToN(msg, truncOnly) { 80 | var delta = msg.byteLength() * 8 - this.n.bitLength(); 81 | if (delta > 0) msg = msg.ushrn(delta); 82 | if (!truncOnly && msg.cmp(this.n) >= 0) return msg.sub(this.n); 83 | else return msg; 84 | }; 85 | 86 | EC.prototype.sign = function sign(msg, key, enc, options) { 87 | if (typeof enc === 'object') { 88 | options = enc; 89 | enc = null; 90 | } 91 | if (!options) options = {}; 92 | 93 | key = this.keyFromPrivate(key, enc); 94 | msg = this._truncateToN(new BN(msg, 16)); 95 | 96 | // Zero-extend key to provide enough entropy 97 | var bytes = this.n.byteLength(); 98 | var bkey = key.getPrivate().toArray('be', bytes); 99 | 100 | // Zero-extend nonce to have the same byte size as N 101 | var nonce = msg.toArray('be', bytes); 102 | 103 | // Instantiate Hmac_DRBG 104 | var drbg = new HmacDRBG({ 105 | hash: this.hash, 106 | entropy: bkey, 107 | nonce: nonce, 108 | pers: options.pers, 109 | persEnc: options.persEnc || 'utf8', 110 | }); 111 | 112 | // Number of bytes to generate 113 | var ns1 = this.n.sub(new BN(1)); 114 | 115 | for (var iter = 0; ; iter++) { 116 | var k = options.k 117 | ? options.k(iter) 118 | : new BN(drbg.generate(this.n.byteLength())); 119 | k = this._truncateToN(k, true); 120 | if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) continue; 121 | 122 | var kp = this.g.mul(k); 123 | if (kp.isInfinity()) continue; 124 | 125 | var kpX = kp.getX(); 126 | var r = kpX.umod(this.n); 127 | if (r.cmpn(0) === 0) continue; 128 | 129 | var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); 130 | s = s.umod(this.n); 131 | if (s.cmpn(0) === 0) continue; 132 | 133 | var recoveryParam = 134 | (kp.getY().isOdd() ? 1 : 0) | (kpX.cmp(r) !== 0 ? 2 : 0); 135 | 136 | // Use complement of `s`, if it is > `n / 2` 137 | if (options.canonical && s.cmp(this.nh) > 0) { 138 | s = this.n.sub(s); 139 | recoveryParam ^= 1; 140 | } 141 | 142 | return new Signature({ r: r, s: s, recoveryParam: recoveryParam }); 143 | } 144 | }; 145 | 146 | EC.prototype.verify = function verify(msg, signature, key, enc) { 147 | msg = this._truncateToN(new BN(msg, 16)); 148 | key = this.keyFromPublic(key, enc); 149 | signature = new Signature(signature, 'hex'); 150 | 151 | // Perform primitive values validation 152 | var r = signature.r; 153 | var s = signature.s; 154 | if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) return false; 155 | if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) return false; 156 | 157 | // Validate signature 158 | var sinv = s.invm(this.n); 159 | var u1 = sinv.mul(msg).umod(this.n); 160 | var u2 = sinv.mul(r).umod(this.n); 161 | var p; 162 | 163 | if (!this.curve._maxwellTrick) { 164 | p = this.g.mulAdd(u1, key.getPublic(), u2); 165 | if (p.isInfinity()) return false; 166 | 167 | return p.getX().umod(this.n).cmp(r) === 0; 168 | } 169 | 170 | // NOTE: Greg Maxwell's trick, inspired by: 171 | // https://git.io/vad3K 172 | 173 | p = this.g.jmulAdd(u1, key.getPublic(), u2); 174 | if (p.isInfinity()) return false; 175 | 176 | // Compare `p.x` of Jacobian point with `r`, 177 | // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the 178 | // inverse of `p.z^2` 179 | return p.eqXToP(r); 180 | }; 181 | 182 | EC.prototype.recoverPubKey = function (msg, signature, j, enc) { 183 | assert((3 & j) === j, 'The recovery param is more than two bits'); 184 | signature = new Signature(signature, enc); 185 | 186 | var n = this.n; 187 | var e = new BN(msg); 188 | var r = signature.r; 189 | var s = signature.s; 190 | 191 | // A set LSB signifies that the y-coordinate is odd 192 | var isYOdd = j & 1; 193 | var isSecondKey = j >> 1; 194 | if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) 195 | throw new Error('Unable to find sencond key candinate'); 196 | 197 | // 1.1. Let x = r + jn. 198 | if (isSecondKey) r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); 199 | else r = this.curve.pointFromX(r, isYOdd); 200 | 201 | var rInv = signature.r.invm(n); 202 | var s1 = n.sub(e).mul(rInv).umod(n); 203 | var s2 = s.mul(rInv).umod(n); 204 | 205 | // 1.6.1 Compute Q = r^-1 (sR - eG) 206 | // Q = r^-1 (sR + -eG) 207 | return this.g.mulAdd(s1, r, s2); 208 | }; 209 | 210 | EC.prototype.getKeyRecoveryParam = function (e, signature, Q, enc) { 211 | signature = new Signature(signature, enc); 212 | if (signature.recoveryParam !== null) return signature.recoveryParam; 213 | 214 | for (var i = 0; i < 4; i++) { 215 | var Qprime; 216 | try { 217 | Qprime = this.recoverPubKey(e, signature, i); 218 | } catch (e) { 219 | continue; 220 | } 221 | 222 | if (Qprime.eq(Q)) return i; 223 | } 224 | throw new Error('Unable to find valid recovery factor'); 225 | }; 226 | -------------------------------------------------------------------------------- /example/src/bn-elliptic/lib/elliptic/ec/key.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var BN = require('bn.js'); 4 | var utils = require('../utils'); 5 | var assert = utils.assert; 6 | 7 | function KeyPair(ec, options) { 8 | this.ec = ec; 9 | this.priv = null; 10 | this.pub = null; 11 | 12 | // KeyPair(ec, { priv: ..., pub: ... }) 13 | if (options.priv) this._importPrivate(options.priv, options.privEnc); 14 | if (options.pub) this._importPublic(options.pub, options.pubEnc); 15 | } 16 | module.exports = KeyPair; 17 | 18 | KeyPair.fromPublic = function fromPublic(ec, pub, enc) { 19 | if (pub instanceof KeyPair) return pub; 20 | 21 | return new KeyPair(ec, { 22 | pub: pub, 23 | pubEnc: enc, 24 | }); 25 | }; 26 | 27 | KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { 28 | if (priv instanceof KeyPair) return priv; 29 | 30 | return new KeyPair(ec, { 31 | priv: priv, 32 | privEnc: enc, 33 | }); 34 | }; 35 | 36 | KeyPair.prototype.validate = function validate() { 37 | var pub = this.getPublic(); 38 | 39 | if (pub.isInfinity()) return { result: false, reason: 'Invalid public key' }; 40 | if (!pub.validate()) 41 | return { result: false, reason: 'Public key is not a point' }; 42 | if (!pub.mul(this.ec.curve.n).isInfinity()) 43 | return { result: false, reason: 'Public key * N != O' }; 44 | 45 | return { result: true, reason: null }; 46 | }; 47 | 48 | KeyPair.prototype.getPublic = function getPublic(compact, enc) { 49 | // compact is optional argument 50 | if (typeof compact === 'string') { 51 | enc = compact; 52 | compact = null; 53 | } 54 | 55 | if (!this.pub) this.pub = this.ec.g.mul(this.priv); 56 | 57 | if (!enc) return this.pub; 58 | 59 | return this.pub.encode(enc, compact); 60 | }; 61 | 62 | KeyPair.prototype.getPrivate = function getPrivate(enc) { 63 | if (enc === 'hex') return this.priv.toString(16, 2); 64 | else return this.priv; 65 | }; 66 | 67 | KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { 68 | this.priv = new BN(key, enc || 16); 69 | 70 | // Ensure that the priv won't be bigger than n, otherwise we may fail 71 | // in fixed multiplication method 72 | this.priv = this.priv.umod(this.ec.curve.n); 73 | }; 74 | 75 | KeyPair.prototype._importPublic = function _importPublic(key, enc) { 76 | if (key.x || key.y) { 77 | // Montgomery points only have an `x` coordinate. 78 | // Weierstrass/Edwards points on the other hand have both `x` and 79 | // `y` coordinates. 80 | if (this.ec.curve.type === 'mont') { 81 | assert(key.x, 'Need x coordinate'); 82 | } else if ( 83 | this.ec.curve.type === 'short' || 84 | this.ec.curve.type === 'edwards' 85 | ) { 86 | assert(key.x && key.y, 'Need both x and y coordinate'); 87 | } 88 | this.pub = this.ec.curve.point(key.x, key.y); 89 | return; 90 | } 91 | this.pub = this.ec.curve.decodePoint(key, enc); 92 | }; 93 | 94 | // ECDH 95 | KeyPair.prototype.derive = function derive(pub) { 96 | if (!pub.validate()) { 97 | assert(pub.validate(), 'public point not validated'); 98 | } 99 | return pub.mul(this.priv).getX(); 100 | }; 101 | 102 | // ECDSA 103 | KeyPair.prototype.sign = function sign(msg, enc, options) { 104 | return this.ec.sign(msg, this, enc, options); 105 | }; 106 | 107 | KeyPair.prototype.verify = function verify(msg, signature) { 108 | return this.ec.verify(msg, signature, this); 109 | }; 110 | 111 | KeyPair.prototype.inspect = function inspect() { 112 | return ( 113 | '' 118 | ); 119 | }; 120 | -------------------------------------------------------------------------------- /example/src/bn-elliptic/lib/elliptic/ec/signature.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var BN = require('bn.js'); 4 | 5 | var utils = require('../utils'); 6 | var assert = utils.assert; 7 | 8 | function Signature(options, enc) { 9 | if (options instanceof Signature) return options; 10 | 11 | if (this._importDER(options, enc)) return; 12 | 13 | assert(options.r && options.s, 'Signature without r or s'); 14 | this.r = new BN(options.r, 16); 15 | this.s = new BN(options.s, 16); 16 | if (options.recoveryParam === undefined) this.recoveryParam = null; 17 | else this.recoveryParam = options.recoveryParam; 18 | } 19 | module.exports = Signature; 20 | 21 | function Position() { 22 | this.place = 0; 23 | } 24 | 25 | function getLength(buf, p) { 26 | var initial = buf[p.place++]; 27 | if (!(initial & 0x80)) { 28 | return initial; 29 | } 30 | var octetLen = initial & 0xf; 31 | 32 | // Indefinite length or overflow 33 | if (octetLen === 0 || octetLen > 4) { 34 | return false; 35 | } 36 | 37 | var val = 0; 38 | for (var i = 0, off = p.place; i < octetLen; i++, off++) { 39 | val <<= 8; 40 | val |= buf[off]; 41 | val >>>= 0; 42 | } 43 | 44 | // Leading zeroes 45 | if (val <= 0x7f) { 46 | return false; 47 | } 48 | 49 | p.place = off; 50 | return val; 51 | } 52 | 53 | function rmPadding(buf) { 54 | var i = 0; 55 | var len = buf.length - 1; 56 | while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { 57 | i++; 58 | } 59 | if (i === 0) { 60 | return buf; 61 | } 62 | return buf.slice(i); 63 | } 64 | 65 | Signature.prototype._importDER = function _importDER(data, enc) { 66 | data = utils.toArray(data, enc); 67 | var p = new Position(); 68 | if (data[p.place++] !== 0x30) { 69 | return false; 70 | } 71 | var len = getLength(data, p); 72 | if (len === false) { 73 | return false; 74 | } 75 | if (len + p.place !== data.length) { 76 | return false; 77 | } 78 | if (data[p.place++] !== 0x02) { 79 | return false; 80 | } 81 | var rlen = getLength(data, p); 82 | if (rlen === false) { 83 | return false; 84 | } 85 | var r = data.slice(p.place, rlen + p.place); 86 | p.place += rlen; 87 | if (data[p.place++] !== 0x02) { 88 | return false; 89 | } 90 | var slen = getLength(data, p); 91 | if (slen === false) { 92 | return false; 93 | } 94 | if (data.length !== slen + p.place) { 95 | return false; 96 | } 97 | var s = data.slice(p.place, slen + p.place); 98 | if (r[0] === 0) { 99 | if (r[1] & 0x80) { 100 | r = r.slice(1); 101 | } else { 102 | // Leading zeroes 103 | return false; 104 | } 105 | } 106 | if (s[0] === 0) { 107 | if (s[1] & 0x80) { 108 | s = s.slice(1); 109 | } else { 110 | // Leading zeroes 111 | return false; 112 | } 113 | } 114 | 115 | this.r = new BN(r); 116 | this.s = new BN(s); 117 | this.recoveryParam = null; 118 | 119 | return true; 120 | }; 121 | 122 | function constructLength(arr, len) { 123 | if (len < 0x80) { 124 | arr.push(len); 125 | return; 126 | } 127 | var octets = 1 + ((Math.log(len) / Math.LN2) >>> 3); 128 | arr.push(octets | 0x80); 129 | while (--octets) { 130 | arr.push((len >>> (octets << 3)) & 0xff); 131 | } 132 | arr.push(len); 133 | } 134 | 135 | Signature.prototype.toDER = function toDER(enc) { 136 | var r = this.r.toArray(); 137 | var s = this.s.toArray(); 138 | 139 | // Pad values 140 | if (r[0] & 0x80) r = [0].concat(r); 141 | // Pad values 142 | if (s[0] & 0x80) s = [0].concat(s); 143 | 144 | r = rmPadding(r); 145 | s = rmPadding(s); 146 | 147 | while (!s[0] && !(s[1] & 0x80)) { 148 | s = s.slice(1); 149 | } 150 | var arr = [0x02]; 151 | constructLength(arr, r.length); 152 | arr = arr.concat(r); 153 | arr.push(0x02); 154 | constructLength(arr, s.length); 155 | var backHalf = arr.concat(s); 156 | var res = [0x30]; 157 | constructLength(res, backHalf.length); 158 | res = res.concat(backHalf); 159 | return utils.encode(res, enc); 160 | }; 161 | -------------------------------------------------------------------------------- /example/src/bn-elliptic/lib/elliptic/eddsa/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var hash = require('hash.js'); 4 | var curves = require('../curves'); 5 | var utils = require('../utils'); 6 | var assert = utils.assert; 7 | var parseBytes = utils.parseBytes; 8 | var KeyPair = require('./key'); 9 | var Signature = require('./signature'); 10 | 11 | function EDDSA(curve) { 12 | assert(curve === 'ed25519', 'only tested with ed25519 so far'); 13 | 14 | if (!(this instanceof EDDSA)) return new EDDSA(curve); 15 | 16 | curve = curves[curve].curve; 17 | this.curve = curve; 18 | this.g = curve.g; 19 | this.g.precompute(curve.n.bitLength() + 1); 20 | 21 | this.pointClass = curve.point().constructor; 22 | this.encodingLength = Math.ceil(curve.n.bitLength() / 8); 23 | this.hash = hash.sha512; 24 | } 25 | 26 | module.exports = EDDSA; 27 | 28 | /** 29 | * @param {Array|String} message - message bytes 30 | * @param {Array|String|KeyPair} secret - secret bytes or a keypair 31 | * @returns {Signature} - signature 32 | */ 33 | EDDSA.prototype.sign = function sign(message, secret) { 34 | message = parseBytes(message); 35 | var key = this.keyFromSecret(secret); 36 | var r = this.hashInt(key.messagePrefix(), message); 37 | var R = this.g.mul(r); 38 | var Rencoded = this.encodePoint(R); 39 | var s_ = this.hashInt(Rencoded, key.pubBytes(), message).mul(key.priv()); 40 | var S = r.add(s_).umod(this.curve.n); 41 | return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); 42 | }; 43 | 44 | /** 45 | * @param {Array} message - message bytes 46 | * @param {Array|String|Signature} sig - sig bytes 47 | * @param {Array|String|Point|KeyPair} pub - public key 48 | * @returns {Boolean} - true if public key matches sig of message 49 | */ 50 | EDDSA.prototype.verify = function verify(message, sig, pub) { 51 | message = parseBytes(message); 52 | sig = this.makeSignature(sig); 53 | var key = this.keyFromPublic(pub); 54 | var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); 55 | var SG = this.g.mul(sig.S()); 56 | var RplusAh = sig.R().add(key.pub().mul(h)); 57 | return RplusAh.eq(SG); 58 | }; 59 | 60 | EDDSA.prototype.hashInt = function hashInt() { 61 | var hash = this.hash(); 62 | for (var i = 0; i < arguments.length; i++) hash.update(arguments[i]); 63 | return utils.intFromLE(hash.digest()).umod(this.curve.n); 64 | }; 65 | 66 | EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { 67 | return KeyPair.fromPublic(this, pub); 68 | }; 69 | 70 | EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { 71 | return KeyPair.fromSecret(this, secret); 72 | }; 73 | 74 | EDDSA.prototype.makeSignature = function makeSignature(sig) { 75 | if (sig instanceof Signature) return sig; 76 | return new Signature(this, sig); 77 | }; 78 | 79 | /** 80 | * * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 81 | * 82 | * EDDSA defines methods for encoding and decoding points and integers. These are 83 | * helper convenience methods, that pass along to utility functions implied 84 | * parameters. 85 | * 86 | */ 87 | EDDSA.prototype.encodePoint = function encodePoint(point) { 88 | var enc = point.getY().toArray('le', this.encodingLength); 89 | enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; 90 | return enc; 91 | }; 92 | 93 | EDDSA.prototype.decodePoint = function decodePoint(bytes) { 94 | bytes = utils.parseBytes(bytes); 95 | 96 | var lastIx = bytes.length - 1; 97 | var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); 98 | var xIsOdd = (bytes[lastIx] & 0x80) !== 0; 99 | 100 | var y = utils.intFromLE(normed); 101 | return this.curve.pointFromY(y, xIsOdd); 102 | }; 103 | 104 | EDDSA.prototype.encodeInt = function encodeInt(num) { 105 | return num.toArray('le', this.encodingLength); 106 | }; 107 | 108 | EDDSA.prototype.decodeInt = function decodeInt(bytes) { 109 | return utils.intFromLE(bytes); 110 | }; 111 | 112 | EDDSA.prototype.isPoint = function isPoint(val) { 113 | return val instanceof this.pointClass; 114 | }; 115 | -------------------------------------------------------------------------------- /example/src/bn-elliptic/lib/elliptic/eddsa/key.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('../utils'); 4 | var assert = utils.assert; 5 | var parseBytes = utils.parseBytes; 6 | var cachedProperty = utils.cachedProperty; 7 | 8 | /** 9 | * @param {EDDSA} eddsa - instance 10 | * @param {Object} params - public/private key parameters 11 | * 12 | * @param {Array} [params.secret] - secret seed bytes 13 | * @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) 14 | * @param {Array} [params.pub] - public key point encoded as bytes 15 | * 16 | */ 17 | function KeyPair(eddsa, params) { 18 | this.eddsa = eddsa; 19 | this._secret = parseBytes(params.secret); 20 | if (eddsa.isPoint(params.pub)) this._pub = params.pub; 21 | else this._pubBytes = parseBytes(params.pub); 22 | } 23 | 24 | KeyPair.fromPublic = function fromPublic(eddsa, pub) { 25 | if (pub instanceof KeyPair) return pub; 26 | return new KeyPair(eddsa, { pub: pub }); 27 | }; 28 | 29 | KeyPair.fromSecret = function fromSecret(eddsa, secret) { 30 | if (secret instanceof KeyPair) return secret; 31 | return new KeyPair(eddsa, { secret: secret }); 32 | }; 33 | 34 | KeyPair.prototype.secret = function secret() { 35 | return this._secret; 36 | }; 37 | 38 | cachedProperty(KeyPair, 'pubBytes', function pubBytes() { 39 | return this.eddsa.encodePoint(this.pub()); 40 | }); 41 | 42 | cachedProperty(KeyPair, 'pub', function pub() { 43 | if (this._pubBytes) return this.eddsa.decodePoint(this._pubBytes); 44 | return this.eddsa.g.mul(this.priv()); 45 | }); 46 | 47 | cachedProperty(KeyPair, 'privBytes', function privBytes() { 48 | var eddsa = this.eddsa; 49 | var hash = this.hash(); 50 | var lastIx = eddsa.encodingLength - 1; 51 | 52 | var a = hash.slice(0, eddsa.encodingLength); 53 | a[0] &= 248; 54 | a[lastIx] &= 127; 55 | a[lastIx] |= 64; 56 | 57 | return a; 58 | }); 59 | 60 | cachedProperty(KeyPair, 'priv', function priv() { 61 | return this.eddsa.decodeInt(this.privBytes()); 62 | }); 63 | 64 | cachedProperty(KeyPair, 'hash', function hash() { 65 | return this.eddsa.hash().update(this.secret()).digest(); 66 | }); 67 | 68 | cachedProperty(KeyPair, 'messagePrefix', function messagePrefix() { 69 | return this.hash().slice(this.eddsa.encodingLength); 70 | }); 71 | 72 | KeyPair.prototype.sign = function sign(message) { 73 | assert(this._secret, 'KeyPair can only verify'); 74 | return this.eddsa.sign(message, this); 75 | }; 76 | 77 | KeyPair.prototype.verify = function verify(message, sig) { 78 | return this.eddsa.verify(message, sig, this); 79 | }; 80 | 81 | KeyPair.prototype.getSecret = function getSecret(enc) { 82 | assert(this._secret, 'KeyPair is public only'); 83 | return utils.encode(this.secret(), enc); 84 | }; 85 | 86 | KeyPair.prototype.getPublic = function getPublic(enc) { 87 | return utils.encode(this.pubBytes(), enc); 88 | }; 89 | 90 | module.exports = KeyPair; 91 | -------------------------------------------------------------------------------- /example/src/bn-elliptic/lib/elliptic/eddsa/signature.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var BN = require('bn.js'); 4 | var utils = require('../utils'); 5 | var assert = utils.assert; 6 | var cachedProperty = utils.cachedProperty; 7 | var parseBytes = utils.parseBytes; 8 | 9 | /** 10 | * @param {EDDSA} eddsa - eddsa instance 11 | * @param {Array|Object} sig - 12 | * @param {Array|Point} [sig.R] - R point as Point or bytes 13 | * @param {Array|bn} [sig.S] - S scalar as bn or bytes 14 | * @param {Array} [sig.Rencoded] - R point encoded 15 | * @param {Array} [sig.Sencoded] - S scalar encoded 16 | */ 17 | function Signature(eddsa, sig) { 18 | this.eddsa = eddsa; 19 | 20 | if (typeof sig !== 'object') sig = parseBytes(sig); 21 | 22 | if (Array.isArray(sig)) { 23 | sig = { 24 | R: sig.slice(0, eddsa.encodingLength), 25 | S: sig.slice(eddsa.encodingLength), 26 | }; 27 | } 28 | 29 | assert(sig.R && sig.S, 'Signature without R or S'); 30 | 31 | if (eddsa.isPoint(sig.R)) this._R = sig.R; 32 | if (sig.S instanceof BN) this._S = sig.S; 33 | 34 | this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; 35 | this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; 36 | } 37 | 38 | cachedProperty(Signature, 'S', function S() { 39 | return this.eddsa.decodeInt(this.Sencoded()); 40 | }); 41 | 42 | cachedProperty(Signature, 'R', function R() { 43 | return this.eddsa.decodePoint(this.Rencoded()); 44 | }); 45 | 46 | cachedProperty(Signature, 'Rencoded', function Rencoded() { 47 | return this.eddsa.encodePoint(this.R()); 48 | }); 49 | 50 | cachedProperty(Signature, 'Sencoded', function Sencoded() { 51 | return this.eddsa.encodeInt(this.S()); 52 | }); 53 | 54 | Signature.prototype.toBytes = function toBytes() { 55 | return this.Rencoded().concat(this.Sencoded()); 56 | }; 57 | 58 | Signature.prototype.toHex = function toHex() { 59 | return utils.encode(this.toBytes(), 'hex').toUpperCase(); 60 | }; 61 | 62 | module.exports = Signature; 63 | -------------------------------------------------------------------------------- /example/src/bn-elliptic/lib/elliptic/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = exports; 4 | var BN = require('bn.js'); 5 | var minAssert = require('minimalistic-assert'); 6 | var minUtils = require('minimalistic-crypto-utils'); 7 | 8 | utils.assert = minAssert; 9 | utils.toArray = minUtils.toArray; 10 | utils.zero2 = minUtils.zero2; 11 | utils.toHex = minUtils.toHex; 12 | utils.encode = minUtils.encode; 13 | 14 | // Represent num in a w-NAF form 15 | function getNAF(num, w, bits) { 16 | var naf = new Array(Math.max(num.bitLength(), bits) + 1); 17 | naf.fill(0); 18 | 19 | var ws = 1 << (w + 1); 20 | var k = num.clone(); 21 | 22 | for (var i = 0; i < naf.length; i++) { 23 | var z; 24 | var mod = k.andln(ws - 1); 25 | if (k.isOdd()) { 26 | if (mod > (ws >> 1) - 1) z = (ws >> 1) - mod; 27 | else z = mod; 28 | k.isubn(z); 29 | } else { 30 | z = 0; 31 | } 32 | 33 | naf[i] = z; 34 | k.iushrn(1); 35 | } 36 | 37 | return naf; 38 | } 39 | utils.getNAF = getNAF; 40 | 41 | // Represent k1, k2 in a Joint Sparse Form 42 | function getJSF(k1, k2) { 43 | var jsf = [[], []]; 44 | 45 | k1 = k1.clone(); 46 | k2 = k2.clone(); 47 | var d1 = 0; 48 | var d2 = 0; 49 | var m8; 50 | while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { 51 | // First phase 52 | var m14 = (k1.andln(3) + d1) & 3; 53 | var m24 = (k2.andln(3) + d2) & 3; 54 | if (m14 === 3) m14 = -1; 55 | if (m24 === 3) m24 = -1; 56 | var u1; 57 | if ((m14 & 1) === 0) { 58 | u1 = 0; 59 | } else { 60 | m8 = (k1.andln(7) + d1) & 7; 61 | if ((m8 === 3 || m8 === 5) && m24 === 2) u1 = -m14; 62 | else u1 = m14; 63 | } 64 | jsf[0].push(u1); 65 | 66 | var u2; 67 | if ((m24 & 1) === 0) { 68 | u2 = 0; 69 | } else { 70 | m8 = (k2.andln(7) + d2) & 7; 71 | if ((m8 === 3 || m8 === 5) && m14 === 2) u2 = -m24; 72 | else u2 = m24; 73 | } 74 | jsf[1].push(u2); 75 | 76 | // Second phase 77 | if (2 * d1 === u1 + 1) d1 = 1 - d1; 78 | if (2 * d2 === u2 + 1) d2 = 1 - d2; 79 | k1.iushrn(1); 80 | k2.iushrn(1); 81 | } 82 | 83 | return jsf; 84 | } 85 | utils.getJSF = getJSF; 86 | 87 | function cachedProperty(obj, name, computer) { 88 | var key = '_' + name; 89 | obj.prototype[name] = function cachedProperty() { 90 | return this[key] !== undefined 91 | ? this[key] 92 | : (this[key] = computer.call(this)); 93 | }; 94 | } 95 | utils.cachedProperty = cachedProperty; 96 | 97 | function parseBytes(bytes) { 98 | return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : bytes; 99 | } 100 | utils.parseBytes = parseBytes; 101 | 102 | function intFromLE(bytes) { 103 | return new BN(bytes, 'hex', 'le'); 104 | } 105 | utils.intFromLE = intFromLE; 106 | -------------------------------------------------------------------------------- /example/src/bn-elliptic/lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var elliptic = exports; 4 | 5 | elliptic.version = require('../package.json').version; 6 | elliptic.utils = require('./elliptic/utils'); 7 | elliptic.rand = require('brorand'); 8 | elliptic.curve = require('./elliptic/curve'); 9 | elliptic.curves = require('./elliptic/curves'); 10 | 11 | // Protocols 12 | elliptic.ec = require('./elliptic/ec'); 13 | elliptic.eddsa = require('./elliptic/eddsa'); 14 | -------------------------------------------------------------------------------- /example/src/bn-elliptic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bn_elliptic", 3 | "version": "6.5.4", 4 | "description": "EC cryptography", 5 | "main": "lib/elliptic.js", 6 | "files": [ 7 | "lib" 8 | ], 9 | "scripts": { 10 | "lint": "eslint lib test", 11 | "lint:fix": "npm run lint -- --fix", 12 | "unit": "istanbul test _mocha --reporter=spec test/index.js", 13 | "test": "npm run lint && npm run unit", 14 | "version": "grunt dist && git add dist/" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git@github.com:indutny/elliptic" 19 | }, 20 | "keywords": [ 21 | "EC", 22 | "Elliptic", 23 | "curve", 24 | "Cryptography" 25 | ], 26 | "author": "Fedor Indutny ", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/indutny/elliptic/issues" 30 | }, 31 | "homepage": "https://github.com/indutny/elliptic", 32 | "devDependencies": { 33 | "brfs": "^2.0.2", 34 | "coveralls": "^3.1.0", 35 | "eslint": "^7.6.0", 36 | "grunt": "^1.2.1", 37 | "grunt-browserify": "^5.3.0", 38 | "grunt-cli": "^1.3.2", 39 | "grunt-contrib-connect": "^3.0.0", 40 | "grunt-contrib-copy": "^1.0.0", 41 | "grunt-contrib-uglify": "^5.0.0", 42 | "grunt-mocha-istanbul": "^5.0.2", 43 | "grunt-saucelabs": "^9.0.1", 44 | "istanbul": "^0.4.5", 45 | "mocha": "^8.0.1" 46 | }, 47 | "dependencies": { 48 | "bn.js": "^4.11.9", 49 | "brorand": "^1.1.0", 50 | "hash.js": "^1.0.0", 51 | "hmac-drbg": "^1.0.1", 52 | "inherits": "^2.0.4", 53 | "minimalistic-assert": "^1.0.1", 54 | "minimalistic-crypto-utils": "^1.0.1" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /example/src/components/Button.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'; 3 | 4 | type ButtonProps = { 5 | title: string; 6 | onPress: () => void; 7 | }; 8 | 9 | export const Button: React.FC = ({ 10 | title, 11 | onPress, 12 | }: ButtonProps) => { 13 | return ( 14 | 15 | 16 | {title} 17 | 18 | 19 | ); 20 | }; 21 | 22 | const styles = StyleSheet.create({ 23 | container: { 24 | backgroundColor: '#99FFFF', 25 | padding: 10, 26 | borderRadius: 5, 27 | alignContent: 'center', 28 | justifyContent: 'center', 29 | borderWidth: 1, 30 | borderColor: 'black', 31 | }, 32 | }); 33 | -------------------------------------------------------------------------------- /example/src/components/CorrectResultItem.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text, StyleSheet } from 'react-native'; 3 | 4 | type CorrectResultItemProps = { 5 | description: string; 6 | }; 7 | 8 | export const CorrectResultItem: React.FC = ({ 9 | description, 10 | }: CorrectResultItemProps) => { 11 | const emoji = '😎'; 12 | const fullText = emoji + ' [' + description + ']'; 13 | 14 | return ( 15 | 16 | {fullText} 17 | 18 | ); 19 | }; 20 | 21 | const styles = StyleSheet.create({ 22 | scroll: { 23 | flex: 1, 24 | }, 25 | itemContainer: { 26 | borderWidth: 1, 27 | margin: 10, 28 | flexDirection: 'column', 29 | borderRadius: 5, 30 | padding: 5, 31 | }, 32 | text: { 33 | flexShrink: 1, 34 | }, 35 | }); 36 | -------------------------------------------------------------------------------- /example/src/components/IncorrectResultItem.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text, StyleSheet } from 'react-native'; 3 | 4 | type IncorrectResultItemProps = { 5 | description: string; 6 | errorMsg: string; 7 | }; 8 | 9 | export const IncorrectResultItem: React.FC = ({ 10 | description, 11 | errorMsg, 12 | }: IncorrectResultItemProps) => { 13 | const emoji = '😵‍💫'; 14 | const fullText = emoji + ' [' + description + '] ---> ' + errorMsg; 15 | 16 | return ( 17 | 18 | {fullText} 19 | 20 | ); 21 | }; 22 | 23 | const styles = StyleSheet.create({ 24 | scroll: { 25 | flex: 1, 26 | }, 27 | itemContainer: { 28 | borderWidth: 1, 29 | margin: 10, 30 | flexDirection: 'column', 31 | borderRadius: 5, 32 | padding: 5, 33 | }, 34 | text: { 35 | flexShrink: 1, 36 | }, 37 | }); 38 | -------------------------------------------------------------------------------- /example/src/components/Indentator.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, StyleSheet } from 'react-native'; 3 | 4 | type IndentatorProps = { 5 | indentation: number; 6 | children: React.ReactChild; 7 | }; 8 | 9 | export const Indentator: React.FC = ({ 10 | indentation, 11 | children, 12 | }: IndentatorProps) => { 13 | return ( 14 | 15 | 16 | {children} 17 | 18 | ); 19 | }; 20 | 21 | const styles = StyleSheet.create({ 22 | container: { 23 | width: '100%', 24 | padding: 5, 25 | flexDirection: 'row', 26 | alignContent: 'center', 27 | }, 28 | }); 29 | -------------------------------------------------------------------------------- /example/src/components/Suite.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text, StyleSheet } from 'react-native'; 3 | 4 | type SuiteProps = { 5 | description: string; 6 | }; 7 | 8 | export const Suite: React.FC = ({ description }: SuiteProps) => { 9 | const emoji = '↘️ '; 10 | const fullText = emoji + description; 11 | 12 | return ( 13 | 14 | {fullText} 15 | 16 | ); 17 | }; 18 | 19 | const styles = StyleSheet.create({ 20 | scroll: { 21 | flex: 1, 22 | }, 23 | itemContainer: { 24 | borderWidth: 1, 25 | margin: 10, 26 | flexDirection: 'column', 27 | borderRadius: 5, 28 | padding: 5, 29 | }, 30 | text: { 31 | flexShrink: 1, 32 | }, 33 | }); 34 | -------------------------------------------------------------------------------- /example/src/components/TestItem.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Text, StyleSheet } from 'react-native'; 3 | import Checkbox from '@react-native-community/checkbox'; 4 | 5 | type TestItemProps = { 6 | description: string; 7 | value: boolean; 8 | index: number; 9 | onToggle: (index: number) => void; 10 | }; 11 | 12 | export const TestItem: React.FC = ({ 13 | description, 14 | value, 15 | index, 16 | onToggle, 17 | }: TestItemProps) => { 18 | return ( 19 | 20 | {description} 21 | { 24 | onToggle(index); 25 | }} 26 | /> 27 | 28 | ); 29 | }; 30 | 31 | const styles = StyleSheet.create({ 32 | container: { 33 | width: '100%', 34 | padding: 10, 35 | flexDirection: 'row', 36 | alignContent: 'center', 37 | alignItems: 'center', 38 | justifyContent: 'space-evenly', 39 | backgroundColor: '#99CCFF', 40 | marginTop: 10, 41 | }, 42 | }); 43 | -------------------------------------------------------------------------------- /example/src/navigators/Root.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { NavigationContainer } from '@react-navigation/native'; 3 | import { createNativeStackNavigator } from '@react-navigation/native-stack'; 4 | import type { RootStackParamList } from './RootProps'; 5 | 6 | const Stack = createNativeStackNavigator(); 7 | 8 | export const Root: React.FC = () => { 9 | return ( 10 | 11 | 12 | { 15 | const { Entry } = require('./children/Entry/Entry'); 16 | return Entry; 17 | }} 18 | /> 19 | { 22 | const { Benchmarks } = require('./children/benchmarks/Benchmarks'); 23 | return Benchmarks; 24 | }} 25 | /> 26 | { 29 | const { 30 | TestingScreen, 31 | } = require('./children/TestingScreen/TestingScreen'); 32 | return TestingScreen; 33 | }} 34 | /> 35 | 36 | 37 | ); 38 | }; 39 | -------------------------------------------------------------------------------- /example/src/navigators/RootProps.ts: -------------------------------------------------------------------------------- 1 | import type { BenchmarksProps } from './children/benchmarks/BenchmarksProps'; 2 | import type { EntryProps } from './children/Entry/EntryProps'; 3 | import type { TestingScreenProps } from './children/TestingScreen/TestingScreenProps'; 4 | 5 | export type RootStackParamList = { 6 | Entry: EntryProps; 7 | Benchmarks: BenchmarksProps; 8 | TestingScreen: TestingScreenProps; 9 | }; 10 | -------------------------------------------------------------------------------- /example/src/navigators/children/Entry/Entry.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useCallback } from 'react'; 2 | import type { RootStackParamList } from '../../RootProps'; 3 | import type { 4 | NativeStackNavigationProp, 5 | NativeStackScreenProps, 6 | } from '@react-navigation/native-stack'; 7 | import { View, ScrollView, StyleSheet } from 'react-native'; 8 | import { Button } from '../../../components/Button'; 9 | import { useNavigation } from '@react-navigation/native'; 10 | import { TestItem } from '../../../components/TestItem'; 11 | import type { TestItemType } from './TestItemType'; 12 | import { TEST_LIST } from '../../../Testing/TestList'; 13 | 14 | type EntryProps = NativeStackScreenProps; 15 | 16 | const useTests = (): [ 17 | Array, 18 | (index: number) => void, 19 | () => void, 20 | () => void 21 | ] => { 22 | const [tests, setTests] = useState>(TEST_LIST); 23 | 24 | const toggle = useCallback( 25 | (index: number) => { 26 | setTests((tests) => { 27 | tests[index].value = !tests[index].value; 28 | return [...tests]; 29 | }); 30 | }, 31 | [setTests] 32 | ); 33 | 34 | const clearAll = useCallback(() => { 35 | setTests((tests) => { 36 | return tests.map((it) => { 37 | it.value = false; 38 | return it; 39 | }); 40 | }); 41 | }, [setTests]); 42 | 43 | const checkAll = useCallback(() => { 44 | setTests((tests) => { 45 | return tests.map((it) => { 46 | it.value = true; 47 | return it; 48 | }); 49 | }); 50 | }, [setTests]); 51 | 52 | return [tests, toggle, clearAll, checkAll]; 53 | }; 54 | 55 | export const Entry: React.FC = ({}: EntryProps) => { 56 | const [tests, toggle, clearAll, checkAll] = useTests(); 57 | const navigation = 58 | useNavigation>(); 59 | return ( 60 | 61 | 62 | 63 | {tests.map((test, index: number) => ( 64 | 71 | ))} 72 | 73 | 74 | 75 |