mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-02-23 15:20:55 +01:00
Merge remote-tracking branch 'origin/master' into ccfix
This commit is contained in:
commit
7736b5278c
68 changed files with 3407 additions and 508 deletions
24
FAQ.md
Normal file
24
FAQ.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
# FAQ
|
||||
|
||||
## Too much nodejs dependencies! Who audits all of that?
|
||||
|
||||
We do. Really, when we bump deps we glance over the diff, and all versions are
|
||||
pinned. Also we use paid audit solution https://snyk.io which is specifically
|
||||
designed to keep an eye on deps.
|
||||
|
||||
And yes we have too many of them, and PRs cutting deps are welcome
|
||||
(see https://github.com/BlueWallet/BlueWallet/blob/master/CONTRIBUTING.md)
|
||||
|
||||
Also really risky dependencies (like, from not-reputable/anonymous maintainers)
|
||||
we fork and use under our organization, and when we update them from upstream (rarely)
|
||||
we do review the code
|
||||
|
||||
## Does BlueWallet downloads the Bitcoin Headers? I see no place you call blockchain.block.headers so I'm wondering how do you guys deal with the headers, how can you make sure you follow the correct chain in order to make sure you're spending a confirmed UTXO?
|
||||
|
||||
The idea is that by default BW doesn’t use public electrum servers, only
|
||||
ones hosted by bluewallet, so they are kinda trusted. And end-user has an
|
||||
option to change electrum server to something he provides, so he knows what
|
||||
is he doing and trusts his own electrum server.
|
||||
|
||||
We would definitely need proper SPV verification if we used random
|
||||
electrum server every time from a pool of public servers.
|
21
blue_modules/aezeed/LICENSE
Normal file
21
blue_modules/aezeed/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2020 bitcoinjs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
2
blue_modules/aezeed/README.md
Normal file
2
blue_modules/aezeed/README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# aezeed
|
||||
A package for encoding, decoding, and generating mnemonics of the aezeed specification. (WIP)
|
85
blue_modules/aezeed/package.json
Normal file
85
blue_modules/aezeed/package.json
Normal file
|
@ -0,0 +1,85 @@
|
|||
{
|
||||
"_from": "aezeed",
|
||||
"_id": "aezeed@0.0.4",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-KAv2y2AtbqpdtsabCLE+C0G0h4BZLeMHsLCRga3VicYLxD17RflUBJ++c5qdpN6B6fkvK90r6bWg52Z/gMC7gQ==",
|
||||
"_location": "/aezeed",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"registry": true,
|
||||
"raw": "aezeed",
|
||||
"name": "aezeed",
|
||||
"escapedName": "aezeed",
|
||||
"rawSpec": "",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/aezeed/-/aezeed-0.0.4.tgz",
|
||||
"_shasum": "8fce8778d34f5566328f61df7706351cb15873a9",
|
||||
"_spec": "aezeed",
|
||||
"_where": "/home/overtorment/Documents/BlueWallet",
|
||||
"author": {
|
||||
"name": "Jonathan Underwood"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/bitcoinjs/aezeed/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"aez": "^1.0.1",
|
||||
"crc-32": "npm:junderw-crc32c@^1.2.0",
|
||||
"randombytes": "^2.1.0",
|
||||
"scryptsy": "^2.1.0"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "A package for encoding, decoding, and generating mnemonics of the aezeed specification.",
|
||||
"devDependencies": {
|
||||
"@types/jest": "^26.0.10",
|
||||
"@types/node": "^14.6.0",
|
||||
"@types/randombytes": "^2.0.0",
|
||||
"@types/scryptsy": "^2.0.0",
|
||||
"jest": "^26.4.2",
|
||||
"prettier": "^2.1.0",
|
||||
"ts-jest": "^26.2.0",
|
||||
"tslint": "^6.1.3",
|
||||
"typescript": "^4.0.2"
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"homepage": "https://github.com/bitcoinjs/aezeed#readme",
|
||||
"keywords": [
|
||||
"aezeed",
|
||||
"bitcoin",
|
||||
"lightning",
|
||||
"lnd"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "src/cipherseed.js",
|
||||
"name": "aezeed",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/bitcoinjs/aezeed.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run clean && tsc -p tsconfig.json",
|
||||
"clean": "rm -rf src",
|
||||
"coverage": "npm run unit -- --coverage",
|
||||
"format": "npm run prettier -- --write",
|
||||
"format:ci": "npm run prettier -- --check",
|
||||
"gitdiff": "git diff --exit-code",
|
||||
"gitdiff:ci": "npm run build && npm run gitdiff",
|
||||
"lint": "tslint -p tsconfig.json -c tslint.json",
|
||||
"prepublishOnly": "npm run test && npm run gitdiff",
|
||||
"prettier": "prettier 'ts_src/**/*.ts' --single-quote --trailing-comma=all --ignore-path ./.prettierignore",
|
||||
"test": "npm run build && npm run format:ci && npm run lint && npm run unit",
|
||||
"unit": "jest --config=jest.json --runInBand"
|
||||
},
|
||||
"types": "src/cipherseed.d.ts",
|
||||
"version": "0.0.4"
|
||||
}
|
15
blue_modules/aezeed/src/cipherseed.d.ts
vendored
Normal file
15
blue_modules/aezeed/src/cipherseed.d.ts
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
/// <reference types="node" />
|
||||
export declare class CipherSeed {
|
||||
entropy: Buffer;
|
||||
salt: Buffer;
|
||||
internalVersion: number;
|
||||
birthday: number;
|
||||
private static decipher;
|
||||
static fromMnemonic(mnemonic: string, password?: string): CipherSeed;
|
||||
static random(): CipherSeed;
|
||||
static changePassword(mnemonic: string, oldPassword: string | null, newPassword: string): string;
|
||||
constructor(entropy: Buffer, salt: Buffer, internalVersion?: number, birthday?: number);
|
||||
get birthDate(): Date;
|
||||
toMnemonic(password?: string, cipherSeedVersion?: number): string;
|
||||
private encipher;
|
||||
}
|
105
blue_modules/aezeed/src/cipherseed.js
Normal file
105
blue_modules/aezeed/src/cipherseed.js
Normal file
|
@ -0,0 +1,105 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CipherSeed = void 0;
|
||||
const BlueCrypto = require('react-native-blue-crypto');
|
||||
const scrypt = require("scryptsy");
|
||||
const rng = require("randombytes");
|
||||
const mn = require("./mnemonic");
|
||||
const params_1 = require("./params");
|
||||
const aez = require('aez');
|
||||
const crc = require('junderw-crc32c');
|
||||
const BITCOIN_GENESIS = new Date('2009-01-03T18:15:05.000Z').getTime();
|
||||
const daysSinceGenesis = (time) => Math.floor((time.getTime() - BITCOIN_GENESIS) / params_1.ONE_DAY);
|
||||
|
||||
async function scryptWrapper(secret, salt, N, r, p, dkLen, progressCallback) {
|
||||
if (BlueCrypto.isAvailable()) {
|
||||
secret = Buffer.from(secret).toString('hex');
|
||||
salt = Buffer.from(salt).toString('hex');
|
||||
const hex = await BlueCrypto.scrypt(secret, salt, N, r, p, dkLen);
|
||||
return Buffer.from(hex, 'hex');
|
||||
} else {
|
||||
// fallback to js implementation
|
||||
return scrypt(secret, salt, N, r, p, dkLen, progressCallback);
|
||||
}
|
||||
}
|
||||
|
||||
class CipherSeed {
|
||||
constructor(entropy, salt, internalVersion = 0, birthday = daysSinceGenesis(new Date())) {
|
||||
this.entropy = entropy;
|
||||
this.salt = salt;
|
||||
this.internalVersion = internalVersion;
|
||||
this.birthday = birthday;
|
||||
if (entropy && entropy.length !== 16)
|
||||
throw new Error('incorrect entropy length');
|
||||
if (salt && salt.length !== 5)
|
||||
throw new Error('incorrect salt length');
|
||||
}
|
||||
|
||||
static async decipher(cipherBuf, password) {
|
||||
if (cipherBuf[0] >= params_1.PARAMS.length) {
|
||||
throw new Error('Invalid cipherSeedVersion');
|
||||
}
|
||||
const cipherSeedVersion = cipherBuf[0];
|
||||
const params = params_1.PARAMS[cipherSeedVersion];
|
||||
const checksum = Buffer.allocUnsafe(4);
|
||||
const checksumNum = crc.buf(cipherBuf.slice(0, 29));
|
||||
checksum.writeInt32BE(checksumNum);
|
||||
if (!checksum.equals(cipherBuf.slice(29))) {
|
||||
throw new Error('CRC checksum mismatch');
|
||||
}
|
||||
const salt = cipherBuf.slice(24, 29);
|
||||
const key = await scryptWrapper(Buffer.from(password, 'utf8'), salt, params.n, params.r, params.p, 32);
|
||||
const adBytes = Buffer.allocUnsafe(6);
|
||||
adBytes.writeUInt8(cipherSeedVersion, 0);
|
||||
salt.copy(adBytes, 1);
|
||||
const plainText = aez.decrypt(key, null, [adBytes], 4, cipherBuf.slice(1, 24));
|
||||
if (plainText === null)
|
||||
throw new Error('Invalid Password');
|
||||
return new CipherSeed(plainText.slice(3, 19), salt, plainText[0], plainText.readUInt16BE(1));
|
||||
}
|
||||
|
||||
static async fromMnemonic(mnemonic, password = params_1.DEFAULT_PASSWORD) {
|
||||
const bytes = mn.mnemonicToBytes(mnemonic);
|
||||
return await CipherSeed.decipher(bytes, password);
|
||||
}
|
||||
|
||||
static random() {
|
||||
return new CipherSeed(rng(16), rng(5));
|
||||
}
|
||||
|
||||
static async changePassword(mnemonic, oldPassword, newPassword) {
|
||||
const pwd = oldPassword === null ? params_1.DEFAULT_PASSWORD : oldPassword;
|
||||
const cs = await CipherSeed.fromMnemonic(mnemonic, pwd);
|
||||
return await cs.toMnemonic(newPassword);
|
||||
}
|
||||
|
||||
get birthDate() {
|
||||
return new Date(BITCOIN_GENESIS + this.birthday * params_1.ONE_DAY);
|
||||
}
|
||||
|
||||
async toMnemonic(password = params_1.DEFAULT_PASSWORD, cipherSeedVersion = params_1.CIPHER_SEED_VERSION) {
|
||||
return mn.mnemonicFromBytes(await this.encipher(password, cipherSeedVersion));
|
||||
}
|
||||
|
||||
async encipher(password, cipherSeedVersion) {
|
||||
const pwBuf = Buffer.from(password, 'utf8');
|
||||
const params = params_1.PARAMS[cipherSeedVersion];
|
||||
const key = await scryptWrapper(pwBuf, this.salt, params.n, params.r, params.p, 32);
|
||||
const seedBytes = Buffer.allocUnsafe(19);
|
||||
seedBytes.writeUInt8(this.internalVersion, 0);
|
||||
seedBytes.writeUInt16BE(this.birthday, 1);
|
||||
this.entropy.copy(seedBytes, 3);
|
||||
const adBytes = Buffer.allocUnsafe(6);
|
||||
adBytes.writeUInt8(cipherSeedVersion, 0);
|
||||
this.salt.copy(adBytes, 1);
|
||||
const cipherText = aez.encrypt(key, null, [adBytes], 4, seedBytes);
|
||||
const cipherSeedBytes = Buffer.allocUnsafe(33);
|
||||
cipherSeedBytes.writeUInt8(cipherSeedVersion, 0);
|
||||
cipherText.copy(cipherSeedBytes, 1);
|
||||
this.salt.copy(cipherSeedBytes, 24);
|
||||
const checksumNum = crc.buf(cipherSeedBytes.slice(0, 29));
|
||||
cipherSeedBytes.writeInt32BE(checksumNum, 29);
|
||||
return cipherSeedBytes;
|
||||
}
|
||||
}
|
||||
exports.CipherSeed = CipherSeed;
|
3
blue_modules/aezeed/src/mnemonic.d.ts
vendored
Normal file
3
blue_modules/aezeed/src/mnemonic.d.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
/// <reference types="node" />
|
||||
export declare function mnemonicFromBytes(bytes: Buffer): string;
|
||||
export declare function mnemonicToBytes(mnemonic: string): Buffer;
|
2091
blue_modules/aezeed/src/mnemonic.js
Normal file
2091
blue_modules/aezeed/src/mnemonic.js
Normal file
File diff suppressed because it is too large
Load diff
8
blue_modules/aezeed/src/params.d.ts
vendored
Normal file
8
blue_modules/aezeed/src/params.d.ts
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
export declare const PARAMS: {
|
||||
n: number;
|
||||
r: number;
|
||||
p: number;
|
||||
}[];
|
||||
export declare const DEFAULT_PASSWORD = "aezeed";
|
||||
export declare const CIPHER_SEED_VERSION = 0;
|
||||
export declare const ONE_DAY: number;
|
14
blue_modules/aezeed/src/params.js
Normal file
14
blue_modules/aezeed/src/params.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ONE_DAY = exports.CIPHER_SEED_VERSION = exports.DEFAULT_PASSWORD = exports.PARAMS = void 0;
|
||||
exports.PARAMS = [
|
||||
{
|
||||
// version 0
|
||||
n: 32768,
|
||||
r: 8,
|
||||
p: 1,
|
||||
},
|
||||
];
|
||||
exports.DEFAULT_PASSWORD = 'aezeed';
|
||||
exports.CIPHER_SEED_VERSION = 0;
|
||||
exports.ONE_DAY = 24 * 60 * 60 * 1000;
|
|
@ -4,7 +4,7 @@ var assert = require('assert')
|
|||
var Buffer = require('safe-buffer').Buffer
|
||||
var bs58check = require('bs58check')
|
||||
var createHash = require('create-hash')
|
||||
var scrypt = require('./scryptsy')
|
||||
var scrypt = require('scryptsy')
|
||||
var xor = require('buffer-xor/inplace')
|
||||
|
||||
var ecurve = require('ecurve')
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
test/
|
||||
.gitignore
|
||||
.min-wd
|
|
@ -1,70 +0,0 @@
|
|||
scryptsy
|
||||
========
|
||||
|
||||
[](http://travis-ci.org/cryptocoinjs/scryptsy)
|
||||
[](https://coveralls.io/r/cryptocoinjs/scryptsy)
|
||||
[](https://www.npmjs.org/package/scryptsy)
|
||||
|
||||
`scryptsy` is a pure Javascript implementation of the [scrypt][wiki] key derivation function that is fully compatible with Node.js and the browser (via Browserify).
|
||||
|
||||
|
||||
Why?
|
||||
----
|
||||
|
||||
`Scrypt` is an integral part of many crypto currencies. It's a part of the [BIP38](https://github.com/bitcoin/bips/blob/master/bip-0038.mediawiki) standard for encrypting private Bitcoin keys. It also serves as the [proof-of-work system](http://en.wikipedia.org/wiki/Proof-of-work_system) for many crypto currencies, most notably: Litecoin and Dogecoin.
|
||||
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
npm install --save scryptsy
|
||||
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```js
|
||||
var scrypt = require('scryptsy')
|
||||
|
||||
var key = "pleaseletmein"
|
||||
var salt = "SodiumChloride"
|
||||
var data = scrypt(key, salt, 16384, 8, 1, 64)
|
||||
console.log(data.toString('hex'))
|
||||
// => 7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887
|
||||
```
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
### scrypt(key, salt, N, r, p, keyLenBytes, [progressCallback])
|
||||
|
||||
- **key**: The key. Either `Buffer` or `string`.
|
||||
- **salt**: The salt. Either `Buffer` or `string`.
|
||||
- **N**: The number of iterations. `number` (integer)
|
||||
- **r**: Memory factor. `number` (integer)
|
||||
- **p**: Parallelization factor. `number` (integer)
|
||||
- **keyLenBytes**: The number of bytes to return. `number` (integer)
|
||||
- **progressCallback**: Call callback on every `1000` ops. Passes in `{current, total, percent}` as first parameter to `progressCallback()`.
|
||||
|
||||
Returns `Buffer`.
|
||||
|
||||
|
||||
|
||||
Resources
|
||||
---------
|
||||
- [Tarsnap Blurb on Scrypt][tarsnap]
|
||||
- [Scrypt Whitepaper](http://www.tarsnap.com/scrypt/scrypt.pdf)
|
||||
- [IETF Scrypt](https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-00) (Test vector params are [incorrect](https://twitter.com/dchest/status/247734446881640448).)
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT
|
||||
|
||||
|
||||
[wiki]: http://en.wikipedia.org/wiki/Scrypt
|
||||
[tarsnap]: http://www.tarsnap.com/scrypt.html
|
|
@ -1,195 +0,0 @@
|
|||
/* eslint-disable camelcase */
|
||||
let pbkdf2 = require('pbkdf2')
|
||||
|
||||
var MAX_VALUE = 0x7fffffff
|
||||
|
||||
// N = Cpu cost, r = Memory cost, p = parallelization cost
|
||||
async function scrypt (key, salt, N, r, p, dkLen, progressCallback) {
|
||||
if (N === 0 || (N & (N - 1)) !== 0) throw Error('N must be > 0 and a power of 2')
|
||||
|
||||
if (N > MAX_VALUE / 128 / r) throw Error('Parameter N is too large')
|
||||
if (r > MAX_VALUE / 128 / p) throw Error('Parameter r is too large')
|
||||
|
||||
var XY = Buffer.alloc(256 * r)
|
||||
var V = Buffer.alloc(128 * r * N)
|
||||
|
||||
// pseudo global
|
||||
var B32 = new Int32Array(16) // salsa20_8
|
||||
var x = new Int32Array(16) // salsa20_8
|
||||
var _X = Buffer.alloc(64) // blockmix_salsa8
|
||||
|
||||
// pseudo global
|
||||
var B = pbkdf2.pbkdf2Sync(key, salt, 1, p * 128 * r, 'sha256')
|
||||
|
||||
var tickCallback
|
||||
if (progressCallback) {
|
||||
var totalOps = p * N * 2
|
||||
var currentOp = 0
|
||||
|
||||
tickCallback = function () {
|
||||
return new Promise(function(resolve, reject) {
|
||||
++currentOp
|
||||
|
||||
// send progress notifications once every 1,000 ops
|
||||
if (currentOp % 1000 === 0) {
|
||||
progressCallback({
|
||||
current: currentOp,
|
||||
total: totalOps,
|
||||
percent: (currentOp / totalOps) * 100.0
|
||||
})
|
||||
setTimeout(resolve, 10)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < p; i++) {
|
||||
await smix(B, i * 128 * r, r, N, V, XY)
|
||||
if (typeof shold_stop_bip38 !== 'undefined') break;
|
||||
}
|
||||
|
||||
return pbkdf2.pbkdf2Sync(key, B, 1, dkLen, 'sha256')
|
||||
|
||||
// all of these functions are actually moved to the top
|
||||
// due to function hoisting
|
||||
|
||||
async function smix (B, Bi, r, N, V, XY) {
|
||||
var Xi = 0
|
||||
var Yi = 128 * r
|
||||
var i
|
||||
|
||||
B.copy(XY, Xi, Bi, Bi + Yi)
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
XY.copy(V, i * Yi, Xi, Xi + Yi)
|
||||
blockmix_salsa8(XY, Xi, Yi, r)
|
||||
|
||||
if (tickCallback) {
|
||||
await tickCallback()
|
||||
if (typeof shold_stop_bip38 !== 'undefined') break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
var offset = Xi + (2 * r - 1) * 64
|
||||
var j = XY.readUInt32LE(offset) & (N - 1)
|
||||
blockxor(V, j * Yi, XY, Xi, Yi)
|
||||
blockmix_salsa8(XY, Xi, Yi, r)
|
||||
|
||||
if (tickCallback) {
|
||||
await tickCallback()
|
||||
if (typeof shold_stop_bip38 !== 'undefined') break;
|
||||
}
|
||||
}
|
||||
|
||||
XY.copy(B, Bi, Xi, Xi + Yi)
|
||||
}
|
||||
|
||||
function blockmix_salsa8 (BY, Bi, Yi, r) {
|
||||
var i
|
||||
|
||||
arraycopy(BY, Bi + (2 * r - 1) * 64, _X, 0, 64)
|
||||
|
||||
for (i = 0; i < 2 * r; i++) {
|
||||
blockxor(BY, i * 64, _X, 0, 64)
|
||||
salsa20_8(_X)
|
||||
arraycopy(_X, 0, BY, Yi + (i * 64), 64)
|
||||
}
|
||||
|
||||
for (i = 0; i < r; i++) {
|
||||
arraycopy(BY, Yi + (i * 2) * 64, BY, Bi + (i * 64), 64)
|
||||
}
|
||||
|
||||
for (i = 0; i < r; i++) {
|
||||
arraycopy(BY, Yi + (i * 2 + 1) * 64, BY, Bi + (i + r) * 64, 64)
|
||||
}
|
||||
}
|
||||
|
||||
function R (a, b) {
|
||||
return (a << b) | (a >>> (32 - b))
|
||||
}
|
||||
|
||||
function salsa20_8 (B) {
|
||||
var i
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
B32[i] = (B[i * 4 + 0] & 0xff) << 0
|
||||
B32[i] |= (B[i * 4 + 1] & 0xff) << 8
|
||||
B32[i] |= (B[i * 4 + 2] & 0xff) << 16
|
||||
B32[i] |= (B[i * 4 + 3] & 0xff) << 24
|
||||
// B32[i] = B.readUInt32LE(i*4) <--- this is signficantly slower even in Node.js
|
||||
}
|
||||
|
||||
arraycopy(B32, 0, x, 0, 16)
|
||||
|
||||
for (i = 8; i > 0; i -= 2) {
|
||||
x[4] ^= R(x[0] + x[12], 7)
|
||||
x[8] ^= R(x[4] + x[0], 9)
|
||||
x[12] ^= R(x[8] + x[4], 13)
|
||||
x[0] ^= R(x[12] + x[8], 18)
|
||||
x[9] ^= R(x[5] + x[1], 7)
|
||||
x[13] ^= R(x[9] + x[5], 9)
|
||||
x[1] ^= R(x[13] + x[9], 13)
|
||||
x[5] ^= R(x[1] + x[13], 18)
|
||||
x[14] ^= R(x[10] + x[6], 7)
|
||||
x[2] ^= R(x[14] + x[10], 9)
|
||||
x[6] ^= R(x[2] + x[14], 13)
|
||||
x[10] ^= R(x[6] + x[2], 18)
|
||||
x[3] ^= R(x[15] + x[11], 7)
|
||||
x[7] ^= R(x[3] + x[15], 9)
|
||||
x[11] ^= R(x[7] + x[3], 13)
|
||||
x[15] ^= R(x[11] + x[7], 18)
|
||||
x[1] ^= R(x[0] + x[3], 7)
|
||||
x[2] ^= R(x[1] + x[0], 9)
|
||||
x[3] ^= R(x[2] + x[1], 13)
|
||||
x[0] ^= R(x[3] + x[2], 18)
|
||||
x[6] ^= R(x[5] + x[4], 7)
|
||||
x[7] ^= R(x[6] + x[5], 9)
|
||||
x[4] ^= R(x[7] + x[6], 13)
|
||||
x[5] ^= R(x[4] + x[7], 18)
|
||||
x[11] ^= R(x[10] + x[9], 7)
|
||||
x[8] ^= R(x[11] + x[10], 9)
|
||||
x[9] ^= R(x[8] + x[11], 13)
|
||||
x[10] ^= R(x[9] + x[8], 18)
|
||||
x[12] ^= R(x[15] + x[14], 7)
|
||||
x[13] ^= R(x[12] + x[15], 9)
|
||||
x[14] ^= R(x[13] + x[12], 13)
|
||||
x[15] ^= R(x[14] + x[13], 18)
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; ++i) B32[i] = x[i] + B32[i]
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
var bi = i * 4
|
||||
B[bi + 0] = (B32[i] >> 0 & 0xff)
|
||||
B[bi + 1] = (B32[i] >> 8 & 0xff)
|
||||
B[bi + 2] = (B32[i] >> 16 & 0xff)
|
||||
B[bi + 3] = (B32[i] >> 24 & 0xff)
|
||||
// B.writeInt32LE(B32[i], i*4) //<--- this is signficantly slower even in Node.js
|
||||
}
|
||||
}
|
||||
|
||||
// naive approach... going back to loop unrolling may yield additional performance
|
||||
function blockxor (S, Si, D, Di, len) {
|
||||
for (var i = 0; i < len; i++) {
|
||||
D[Di + i] ^= S[Si + i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function arraycopy (src, srcPos, dest, destPos, length) {
|
||||
if (Buffer.isBuffer(src) && Buffer.isBuffer(dest)) {
|
||||
src.copy(dest, destPos, srcPos, srcPos + length)
|
||||
} else {
|
||||
while (length--) {
|
||||
dest[destPos++] = src[srcPos++]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = scrypt
|
|
@ -1,87 +0,0 @@
|
|||
{
|
||||
"_from": "scryptsy@^2.0.0",
|
||||
"_id": "scryptsy@2.0.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-Jiw28CMc+nZU4jY/o5TNLexm83g=",
|
||||
"_location": "/scryptsy",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "scryptsy@^2.0.0",
|
||||
"name": "scryptsy",
|
||||
"escapedName": "scryptsy",
|
||||
"rawSpec": "^2.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^2.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.0.0.tgz",
|
||||
"_shasum": "262c36f0231cfa7654e2363fa394cd2dec66f378",
|
||||
"_spec": "scryptsy@^2.0.0",
|
||||
"_where": "/home/burn/Documents/bip38",
|
||||
"author": "",
|
||||
"bugs": {
|
||||
"url": "https://github.com/cryptocoinjs/scryptsy/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {},
|
||||
"deprecated": false,
|
||||
"description": "Pure JavaScript implementation of the scrypt key deriviation function that is fully compatible with Node.js and the browser.",
|
||||
"devDependencies": {
|
||||
"coveralls": "^2.10.0",
|
||||
"istanbul": "^0.3.5",
|
||||
"mocha": "^2.2.0",
|
||||
"mochify": "^2.1.0",
|
||||
"standard": "^7.1.1"
|
||||
},
|
||||
"homepage": "https://github.com/cryptocoinjs/scryptsy#readme",
|
||||
"keywords": [
|
||||
"crytpo",
|
||||
"cryptography",
|
||||
"scrypt",
|
||||
"kdf",
|
||||
"litecoin",
|
||||
"dogecoin",
|
||||
"bitcoin",
|
||||
"bip38"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "lib/scrypt.js",
|
||||
"name": "scryptsy",
|
||||
"repository": {
|
||||
"url": "git+ssh://git@github.com/cryptocoinjs/scryptsy.git",
|
||||
"type": "git"
|
||||
},
|
||||
"scripts": {
|
||||
"browser-test": "mochify --wd -R spec",
|
||||
"coverage": "istanbul cover ./node_modules/.bin/_mocha -- --reporter list test/*.js",
|
||||
"coveralls": "npm run-script coverage && node ./node_modules/.bin/coveralls < coverage/lcov.info",
|
||||
"lint": "standard",
|
||||
"test": "mocha --ui bdd",
|
||||
"unit": "mocha"
|
||||
},
|
||||
"version": "2.0.0",
|
||||
"react-native": {
|
||||
"path": "path-browserify",
|
||||
"fs": "react-native-level-fs",
|
||||
"_stream_transform": "readable-stream/transform",
|
||||
"_stream_readable": "readable-stream/readable",
|
||||
"_stream_writable": "readable-stream/writable",
|
||||
"_stream_duplex": "readable-stream/duplex",
|
||||
"_stream_passthrough": "readable-stream/passthrough",
|
||||
"stream": "stream-browserify"
|
||||
},
|
||||
"browser": {
|
||||
"path": "path-browserify",
|
||||
"fs": "react-native-level-fs",
|
||||
"_stream_transform": "readable-stream/transform",
|
||||
"_stream_readable": "readable-stream/readable",
|
||||
"_stream_writable": "readable-stream/writable",
|
||||
"_stream_duplex": "readable-stream/duplex",
|
||||
"_stream_passthrough": "readable-stream/passthrough",
|
||||
"stream": "stream-browserify"
|
||||
}
|
||||
}
|
|
@ -1,3 +1,9 @@
|
|||
3.0.0 / 2019-03-12
|
||||
------------------
|
||||
- **breaking** Import gives an object with two functions `scrypt` and `scryptSync`
|
||||
- `scryptSync` is the old synchronus function.
|
||||
- `scrypt` will return a promise with the buffer.
|
||||
|
||||
2.0.0 / 2016-05-26
|
||||
------------------
|
||||
- **breaking** Node v0.10 not supported anymore.
|
21
blue_modules/scryptsy/LICENSE
Normal file
21
blue_modules/scryptsy/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018 cryptocoinjs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
157
blue_modules/scryptsy/README.md
Normal file
157
blue_modules/scryptsy/README.md
Normal file
|
@ -0,0 +1,157 @@
|
|||
scryptsy
|
||||
========
|
||||
|
||||
[](http://travis-ci.org/cryptocoinjs/scryptsy)
|
||||
[](https://coveralls.io/r/cryptocoinjs/scryptsy)
|
||||
[](https://www.npmjs.org/package/scryptsy)
|
||||
|
||||
`scryptsy` is a pure Javascript implementation of the [scrypt][wiki] key derivation function that is fully compatible with Node.js and the browser (via Browserify).
|
||||
|
||||
|
||||
Why?
|
||||
----
|
||||
|
||||
`Scrypt` is an integral part of many crypto currencies. It's a part of the [BIP38](https://github.com/bitcoin/bips/blob/master/bip-0038.mediawiki) standard for encrypting private Bitcoin keys. It also serves as the [proof-of-work system](http://en.wikipedia.org/wiki/Proof-of-work_system) for many crypto currencies, most notably: Litecoin and Dogecoin.
|
||||
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
npm install --save scryptsy
|
||||
|
||||
|
||||
|
||||
Browserify Note
|
||||
------------
|
||||
|
||||
When using a browserified bundle, be sure to add `setImmediate` as a shim.
|
||||
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```js
|
||||
const scrypt = require('scryptsy')
|
||||
|
||||
async function main () {
|
||||
var key = "pleaseletmein"
|
||||
var salt = "SodiumChloride"
|
||||
var data1 = scrypt(key, salt, 16384, 8, 1, 64)
|
||||
console.log(data1.toString('hex'))
|
||||
// => 7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887
|
||||
|
||||
// async is actually slower, but it will free up the event loop occasionally
|
||||
// which will allow for front end GUI elements to update and cause it to not
|
||||
// freeze up.
|
||||
// See benchmarks below
|
||||
// Passing 300 below means every 300 iterations internally will call setImmediate once
|
||||
var data2 = await scrypt.async(key, salt, 16384, 8, 1, 64, undefined, 300)
|
||||
console.log(data2.toString('hex'))
|
||||
// => 7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887
|
||||
}
|
||||
main().catch(console.error)
|
||||
```
|
||||
|
||||
|
||||
Benchmarks
|
||||
-------
|
||||
|
||||
Internal iterations are N * p, so changing r doesn't affect the number of calls to setImmediate.
|
||||
Decreasing pI decreases performance in exchange for more frequently freeing the event loop.
|
||||
(pI Default is 5000 loops per setImmediate call)
|
||||
|
||||
Note: these benchmarks were done on node v10 on a CPU with good single thread performance.
|
||||
browsers show a much larger difference. Please tinker with the pI setting to balance between
|
||||
performance and GUI responsiveness.
|
||||
|
||||
If `pI >= N`, setImmediate will only be called `p * 2` times total (on the i = 0 of each for loop).
|
||||
|
||||
```
|
||||
---------------------------
|
||||
time : type : (N,r,p,pI) (pI = promiseInterval)
|
||||
---------------------------
|
||||
2266 ms : sync (2^16,16,1)
|
||||
2548 ms : async (2^16,16,1,5000)
|
||||
12.44% increase
|
||||
---------------------------
|
||||
2616 ms : sync (2^16,1,16)
|
||||
2995 ms : async (2^16,1,16,5000)
|
||||
14.49% increase
|
||||
---------------------------
|
||||
2685 ms : sync (2^20,1,1)
|
||||
3090 ms : async (2^20,1,1,5000)
|
||||
15.08% increase
|
||||
---------------------------
|
||||
2235 ms : sync (2^16,16,1)
|
||||
2627 ms : async (2^16,16,1,10)
|
||||
17.54% increase
|
||||
---------------------------
|
||||
2592 ms : sync (2^16,1,16)
|
||||
3305 ms : async (2^16,1,16,10)
|
||||
27.51% increase
|
||||
---------------------------
|
||||
2705 ms : sync (2^20,1,1)
|
||||
3363 ms : async (2^20,1,1,10)
|
||||
24.33% increase
|
||||
---------------------------
|
||||
2278 ms : sync (2^16,16,1)
|
||||
2773 ms : async (2^16,16,1,1)
|
||||
21.73% increase
|
||||
---------------------------
|
||||
2617 ms : sync (2^16,1,16)
|
||||
5632 ms : async (2^16,1,16,1)
|
||||
115.21% increase
|
||||
---------------------------
|
||||
2727 ms : sync (2^20,1,1)
|
||||
5723 ms : async (2^20,1,1,1)
|
||||
109.86% increase
|
||||
---------------------------
|
||||
```
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
### scrypt(key, salt, N, r, p, keyLenBytes, [progressCallback])
|
||||
|
||||
- **key**: The key. Either `Buffer` or `string`.
|
||||
- **salt**: The salt. Either `Buffer` or `string`.
|
||||
- **N**: The number of iterations. `number` (integer)
|
||||
- **r**: Memory factor. `number` (integer)
|
||||
- **p**: Parallelization factor. `number` (integer)
|
||||
- **keyLenBytes**: The number of bytes to return. `number` (integer)
|
||||
- **progressCallback**: Call callback on every `1000` ops. Passes in `{current, total, percent}` as first parameter to `progressCallback()`.
|
||||
|
||||
Returns `Buffer`.
|
||||
|
||||
### scrypt.async(key, salt, N, r, p, keyLenBytes, [progressCallback, promiseInterval])
|
||||
|
||||
- **key**: The key. Either `Buffer` or `string`.
|
||||
- **salt**: The salt. Either `Buffer` or `string`.
|
||||
- **N**: The number of iterations. `number` (integer)
|
||||
- **r**: Memory factor. `number` (integer)
|
||||
- **p**: Parallelization factor. `number` (integer)
|
||||
- **keyLenBytes**: The number of bytes to return. `number` (integer)
|
||||
- **progressCallback**: Call callback on every `1000` ops. Passes in `{current, total, percent}` as first parameter to `progressCallback()`.
|
||||
- **promiseInterval**: The number of internal iterations before calling setImmediate once to free the event loop.
|
||||
|
||||
Returns `Promise<Buffer>`.
|
||||
|
||||
|
||||
|
||||
Resources
|
||||
---------
|
||||
- [Tarsnap Blurb on Scrypt][tarsnap]
|
||||
- [Scrypt Whitepaper](http://www.tarsnap.com/scrypt/scrypt.pdf)
|
||||
- [IETF Scrypt](https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-00) (Test vector params are [incorrect](https://twitter.com/dchest/status/247734446881640448).)
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT
|
||||
|
||||
|
||||
[wiki]: http://en.wikipedia.org/wiki/Scrypt
|
||||
[tarsnap]: http://www.tarsnap.com/scrypt.html
|
3
blue_modules/scryptsy/lib/index.js
Normal file
3
blue_modules/scryptsy/lib/index.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
const scrypt = require('./scryptSync')
|
||||
scrypt.async = require('./scrypt')
|
||||
module.exports = scrypt
|
26
blue_modules/scryptsy/lib/scrypt.js
Normal file
26
blue_modules/scryptsy/lib/scrypt.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
let pbkdf2 = require('pbkdf2')
|
||||
const {
|
||||
checkAndInit,
|
||||
smix
|
||||
} = require('./utils')
|
||||
|
||||
// N = Cpu cost, r = Memory cost, p = parallelization cost
|
||||
async function scrypt (key, salt, N, r, p, dkLen, progressCallback, promiseInterval) {
|
||||
const {
|
||||
XY,
|
||||
V,
|
||||
B32,
|
||||
x,
|
||||
_X,
|
||||
B,
|
||||
tickCallback
|
||||
} = checkAndInit(key, salt, N, r, p, dkLen, progressCallback)
|
||||
|
||||
for (var i = 0; i < p; i++) {
|
||||
await smix(B, i * 128 * r, r, N, V, XY, _X, B32, x, tickCallback, promiseInterval)
|
||||
}
|
||||
|
||||
return pbkdf2.pbkdf2Sync(key, B, 1, dkLen, 'sha256')
|
||||
}
|
||||
|
||||
module.exports = scrypt
|
26
blue_modules/scryptsy/lib/scryptSync.js
Normal file
26
blue_modules/scryptsy/lib/scryptSync.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
let pbkdf2 = require('pbkdf2')
|
||||
const {
|
||||
checkAndInit,
|
||||
smixSync
|
||||
} = require('./utils')
|
||||
|
||||
// N = Cpu cost, r = Memory cost, p = parallelization cost
|
||||
function scrypt (key, salt, N, r, p, dkLen, progressCallback) {
|
||||
const {
|
||||
XY,
|
||||
V,
|
||||
B32,
|
||||
x,
|
||||
_X,
|
||||
B,
|
||||
tickCallback
|
||||
} = checkAndInit(key, salt, N, r, p, dkLen, progressCallback)
|
||||
|
||||
for (var i = 0; i < p; i++) {
|
||||
smixSync(B, i * 128 * r, r, N, V, XY, _X, B32, x, tickCallback)
|
||||
}
|
||||
|
||||
return pbkdf2.pbkdf2Sync(key, B, 1, dkLen, 'sha256')
|
||||
}
|
||||
|
||||
module.exports = scrypt
|
216
blue_modules/scryptsy/lib/utils.js
Normal file
216
blue_modules/scryptsy/lib/utils.js
Normal file
|
@ -0,0 +1,216 @@
|
|||
let pbkdf2 = require('pbkdf2')
|
||||
const MAX_VALUE = 0x7fffffff
|
||||
const DEFAULT_PROMISE_INTERVAL = 5000
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
function checkAndInit (key, salt, N, r, p, dkLen, progressCallback) {
|
||||
if (N === 0 || (N & (N - 1)) !== 0) throw Error('N must be > 0 and a power of 2')
|
||||
|
||||
if (N > MAX_VALUE / 128 / r) throw Error('Parameter N is too large')
|
||||
if (r > MAX_VALUE / 128 / p) throw Error('Parameter r is too large')
|
||||
|
||||
let XY = Buffer.alloc(256 * r)
|
||||
let V = Buffer.alloc(128 * r * N)
|
||||
|
||||
// pseudo global
|
||||
let B32 = new Int32Array(16) // salsa20_8
|
||||
let x = new Int32Array(16) // salsa20_8
|
||||
let _X = Buffer.alloc(64) // blockmix_salsa8
|
||||
|
||||
// pseudo global
|
||||
let B = pbkdf2.pbkdf2Sync(key, salt, 1, p * 128 * r, 'sha256')
|
||||
|
||||
let tickCallback
|
||||
if (progressCallback) {
|
||||
let totalOps = p * N * 2
|
||||
let currentOp = 0
|
||||
|
||||
tickCallback = function () {
|
||||
++currentOp
|
||||
|
||||
// send progress notifications once every 1,000 ops
|
||||
if (currentOp % 1000 === 0) {
|
||||
progressCallback({
|
||||
current: currentOp,
|
||||
total: totalOps,
|
||||
percent: (currentOp / totalOps) * 100.0
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
XY,
|
||||
V,
|
||||
B32,
|
||||
x,
|
||||
_X,
|
||||
B,
|
||||
tickCallback
|
||||
}
|
||||
}
|
||||
|
||||
async function smix (B, Bi, r, N, V, XY, _X, B32, x, tickCallback, promiseInterval) {
|
||||
promiseInterval = promiseInterval || DEFAULT_PROMISE_INTERVAL
|
||||
let Xi = 0
|
||||
let Yi = 128 * r
|
||||
let i
|
||||
|
||||
B.copy(XY, Xi, Bi, Bi + Yi)
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
XY.copy(V, i * Yi, Xi, Xi + Yi)
|
||||
if (i % promiseInterval === 0) {
|
||||
await new Promise(resolve => setImmediate(resolve))
|
||||
}
|
||||
blockmix_salsa8(XY, Xi, Yi, r, _X, B32, x)
|
||||
|
||||
if (tickCallback) tickCallback()
|
||||
}
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
let offset = Xi + (2 * r - 1) * 64
|
||||
let j = XY.readUInt32LE(offset) & (N - 1)
|
||||
blockxor(V, j * Yi, XY, Xi, Yi)
|
||||
if (i % promiseInterval === 0) {
|
||||
await new Promise(resolve => setImmediate(resolve))
|
||||
}
|
||||
blockmix_salsa8(XY, Xi, Yi, r, _X, B32, x)
|
||||
|
||||
if (tickCallback) tickCallback()
|
||||
}
|
||||
|
||||
XY.copy(B, Bi, Xi, Xi + Yi)
|
||||
}
|
||||
|
||||
function smixSync (B, Bi, r, N, V, XY, _X, B32, x, tickCallback) {
|
||||
let Xi = 0
|
||||
let Yi = 128 * r
|
||||
let i
|
||||
|
||||
B.copy(XY, Xi, Bi, Bi + Yi)
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
XY.copy(V, i * Yi, Xi, Xi + Yi)
|
||||
blockmix_salsa8(XY, Xi, Yi, r, _X, B32, x)
|
||||
|
||||
if (tickCallback) tickCallback()
|
||||
}
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
let offset = Xi + (2 * r - 1) * 64
|
||||
let j = XY.readUInt32LE(offset) & (N - 1)
|
||||
blockxor(V, j * Yi, XY, Xi, Yi)
|
||||
blockmix_salsa8(XY, Xi, Yi, r, _X, B32, x)
|
||||
|
||||
if (tickCallback) tickCallback()
|
||||
}
|
||||
|
||||
XY.copy(B, Bi, Xi, Xi + Yi)
|
||||
}
|
||||
|
||||
function blockmix_salsa8 (BY, Bi, Yi, r, _X, B32, x) {
|
||||
let i
|
||||
|
||||
arraycopy(BY, Bi + (2 * r - 1) * 64, _X, 0, 64)
|
||||
|
||||
for (i = 0; i < 2 * r; i++) {
|
||||
blockxor(BY, i * 64, _X, 0, 64)
|
||||
salsa20_8(_X, B32, x)
|
||||
arraycopy(_X, 0, BY, Yi + (i * 64), 64)
|
||||
}
|
||||
|
||||
for (i = 0; i < r; i++) {
|
||||
arraycopy(BY, Yi + (i * 2) * 64, BY, Bi + (i * 64), 64)
|
||||
}
|
||||
|
||||
for (i = 0; i < r; i++) {
|
||||
arraycopy(BY, Yi + (i * 2 + 1) * 64, BY, Bi + (i + r) * 64, 64)
|
||||
}
|
||||
}
|
||||
|
||||
function R (a, b) {
|
||||
return (a << b) | (a >>> (32 - b))
|
||||
}
|
||||
|
||||
function salsa20_8 (B, B32, x) {
|
||||
let i
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
B32[i] = (B[i * 4 + 0] & 0xff) << 0
|
||||
B32[i] |= (B[i * 4 + 1] & 0xff) << 8
|
||||
B32[i] |= (B[i * 4 + 2] & 0xff) << 16
|
||||
B32[i] |= (B[i * 4 + 3] & 0xff) << 24
|
||||
// B32[i] = B.readUInt32LE(i*4) <--- this is signficantly slower even in Node.js
|
||||
}
|
||||
|
||||
arraycopy(B32, 0, x, 0, 16)
|
||||
|
||||
for (i = 8; i > 0; i -= 2) {
|
||||
x[4] ^= R(x[0] + x[12], 7)
|
||||
x[8] ^= R(x[4] + x[0], 9)
|
||||
x[12] ^= R(x[8] + x[4], 13)
|
||||
x[0] ^= R(x[12] + x[8], 18)
|
||||
x[9] ^= R(x[5] + x[1], 7)
|
||||
x[13] ^= R(x[9] + x[5], 9)
|
||||
x[1] ^= R(x[13] + x[9], 13)
|
||||
x[5] ^= R(x[1] + x[13], 18)
|
||||
x[14] ^= R(x[10] + x[6], 7)
|
||||
x[2] ^= R(x[14] + x[10], 9)
|
||||
x[6] ^= R(x[2] + x[14], 13)
|
||||
x[10] ^= R(x[6] + x[2], 18)
|
||||
x[3] ^= R(x[15] + x[11], 7)
|
||||
x[7] ^= R(x[3] + x[15], 9)
|
||||
x[11] ^= R(x[7] + x[3], 13)
|
||||
x[15] ^= R(x[11] + x[7], 18)
|
||||
x[1] ^= R(x[0] + x[3], 7)
|
||||
x[2] ^= R(x[1] + x[0], 9)
|
||||
x[3] ^= R(x[2] + x[1], 13)
|
||||
x[0] ^= R(x[3] + x[2], 18)
|
||||
x[6] ^= R(x[5] + x[4], 7)
|
||||
x[7] ^= R(x[6] + x[5], 9)
|
||||
x[4] ^= R(x[7] + x[6], 13)
|
||||
x[5] ^= R(x[4] + x[7], 18)
|
||||
x[11] ^= R(x[10] + x[9], 7)
|
||||
x[8] ^= R(x[11] + x[10], 9)
|
||||
x[9] ^= R(x[8] + x[11], 13)
|
||||
x[10] ^= R(x[9] + x[8], 18)
|
||||
x[12] ^= R(x[15] + x[14], 7)
|
||||
x[13] ^= R(x[12] + x[15], 9)
|
||||
x[14] ^= R(x[13] + x[12], 13)
|
||||
x[15] ^= R(x[14] + x[13], 18)
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; ++i) B32[i] = x[i] + B32[i]
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
let bi = i * 4
|
||||
B[bi + 0] = (B32[i] >> 0 & 0xff)
|
||||
B[bi + 1] = (B32[i] >> 8 & 0xff)
|
||||
B[bi + 2] = (B32[i] >> 16 & 0xff)
|
||||
B[bi + 3] = (B32[i] >> 24 & 0xff)
|
||||
// B.writeInt32LE(B32[i], i*4) //<--- this is signficantly slower even in Node.js
|
||||
}
|
||||
}
|
||||
|
||||
// naive approach... going back to loop unrolling may yield additional performance
|
||||
function blockxor (S, Si, D, Di, len) {
|
||||
for (let i = 0; i < len; i++) {
|
||||
D[Di + i] ^= S[Si + i]
|
||||
}
|
||||
}
|
||||
|
||||
function arraycopy (src, srcPos, dest, destPos, length) {
|
||||
if (Buffer.isBuffer(src) && Buffer.isBuffer(dest)) {
|
||||
src.copy(dest, destPos, srcPos, srcPos + length)
|
||||
} else {
|
||||
while (length--) {
|
||||
dest[destPos++] = src[srcPos++]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
checkAndInit,
|
||||
smix,
|
||||
smixSync
|
||||
}
|
71
blue_modules/scryptsy/package.json
Normal file
71
blue_modules/scryptsy/package.json
Normal file
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"_from": "scryptsy@2.1.0",
|
||||
"_id": "scryptsy@2.1.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==",
|
||||
"_location": "/scryptsy",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "scryptsy@2.1.0",
|
||||
"name": "scryptsy",
|
||||
"escapedName": "scryptsy",
|
||||
"rawSpec": "2.1.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "2.1.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz",
|
||||
"_shasum": "8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790",
|
||||
"_spec": "scryptsy@2.1.0",
|
||||
"_where": "/home/overtorment/Documents/BlueWallet",
|
||||
"author": "",
|
||||
"bugs": {
|
||||
"url": "https://github.com/cryptocoinjs/scryptsy/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {},
|
||||
"deprecated": false,
|
||||
"description": "Pure JavaScript implementation of the scrypt key deriviation function that is fully compatible with Node.js and the browser.",
|
||||
"devDependencies": {
|
||||
"coveralls": "^3.0.3",
|
||||
"mocha": "^6.0.2",
|
||||
"mochify": "^6.1.0",
|
||||
"nyc": "^13.3.0",
|
||||
"standard": "^12.0.1"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"homepage": "https://github.com/cryptocoinjs/scryptsy#readme",
|
||||
"keywords": [
|
||||
"crytpo",
|
||||
"cryptography",
|
||||
"scrypt",
|
||||
"kdf",
|
||||
"litecoin",
|
||||
"dogecoin",
|
||||
"bitcoin",
|
||||
"bip38"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"name": "scryptsy",
|
||||
"repository": {
|
||||
"url": "git+ssh://git@github.com/cryptocoinjs/scryptsy.git",
|
||||
"type": "git"
|
||||
},
|
||||
"scripts": {
|
||||
"browser-test": "mochify --wd -R spec",
|
||||
"coverage": "nyc --check-coverage --statements 80 --branches 60 --functions 90 --lines 90 mocha",
|
||||
"coveralls": "npm run-script coverage && coveralls < coverage/lcov.info",
|
||||
"lint": "standard",
|
||||
"test": "mocha --ui bdd",
|
||||
"unit": "mocha"
|
||||
},
|
||||
"version": "2.1.0"
|
||||
}
|
|
@ -14,6 +14,7 @@ import {
|
|||
LightningCustodianWallet,
|
||||
HDLegacyElectrumSeedP2PKHWallet,
|
||||
HDSegwitElectrumSeedP2WPKHWallet,
|
||||
HDAezeedWallet,
|
||||
MultisigHDWallet,
|
||||
} from './';
|
||||
const encryption = require('../blue_modules/encryption');
|
||||
|
@ -275,6 +276,9 @@ export class AppStorage {
|
|||
case MultisigHDWallet.type:
|
||||
unserializedWallet = MultisigHDWallet.fromJson(key);
|
||||
break;
|
||||
case HDAezeedWallet.type:
|
||||
unserializedWallet = HDAezeedWallet.fromJson(key);
|
||||
break;
|
||||
case LightningCustodianWallet.type: {
|
||||
/** @type {LightningCustodianWallet} */
|
||||
unserializedWallet = LightningCustodianWallet.fromJson(key);
|
||||
|
|
|
@ -76,39 +76,6 @@ export class HodlHodlApi {
|
|||
return (this._countries = json.countries);
|
||||
}
|
||||
|
||||
async getMyCountryCode() {
|
||||
const _api = new Frisbee({ baseURI: 'https://ifconfig.co/' });
|
||||
const _api2 = new Frisbee({ baseURI: 'https://geolocation-db.com/' });
|
||||
let response;
|
||||
|
||||
let allowedTries = 6;
|
||||
while (allowedTries > 0) {
|
||||
// this API fails a lot, so lets retry several times
|
||||
response = await _api.get('/country-iso', { headers: { 'Access-Control-Allow-Origin': '*' } });
|
||||
|
||||
let body = response.body;
|
||||
if (typeof body === 'string') body = body.replace('\n', '');
|
||||
if (!body || body.length !== 2) {
|
||||
// trying api2
|
||||
const response = await _api2.get('/json/', { headers: { 'Access-Control-Allow-Origin': '*' } });
|
||||
body = response.body;
|
||||
let json;
|
||||
try {
|
||||
json = JSON.parse(body);
|
||||
} catch (_) {}
|
||||
if (json && json.country_code) return (this._myCountryCode = json.country_code);
|
||||
// failed, retry
|
||||
|
||||
allowedTries--;
|
||||
await (async () => new Promise(resolve => setTimeout(resolve, 3000)))(); // sleep
|
||||
} else {
|
||||
return (this._myCountryCode = body);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('API failure after several tries: ' + JSON.stringify(response));
|
||||
}
|
||||
|
||||
async getPaymentMethods(country) {
|
||||
const response = await this._api.get('/api/v1/payment_methods?filters[country]=' + country, this._getHeaders());
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ export * from './wallets/hd-segwit-bech32-wallet';
|
|||
export * from './wallets/placeholder-wallet';
|
||||
export * from './wallets/hd-legacy-electrum-seed-p2pkh-wallet';
|
||||
export * from './wallets/hd-segwit-electrum-seed-p2wpkh-wallet';
|
||||
export * from './wallets/hd-aezeed-wallet';
|
||||
export * from './wallets/multisig-hd-wallet';
|
||||
export * from './hd-segwit-bech32-transaction';
|
||||
export * from './multisig-cosigner';
|
||||
|
|
|
@ -10,6 +10,7 @@ import { SegwitBech32Wallet } from './wallets/segwit-bech32-wallet';
|
|||
import { HDLegacyElectrumSeedP2PKHWallet } from './wallets/hd-legacy-electrum-seed-p2pkh-wallet';
|
||||
import { HDSegwitElectrumSeedP2WPKHWallet } from './wallets/hd-segwit-electrum-seed-p2wpkh-wallet';
|
||||
import { MultisigHDWallet } from './wallets/multisig-hd-wallet';
|
||||
import { HDAezeedWallet } from "./wallets/hd-aezeed-wallet";
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
|
||||
export default class WalletGradient {
|
||||
|
@ -23,6 +24,7 @@ export default class WalletGradient {
|
|||
static multisigHdWallet = ['#1ce6eb', '#296fc5', '#3500A2'];
|
||||
static defaultGradients = ['#c65afb', '#9053fe'];
|
||||
static lightningCustodianWallet = ['#f1be07', '#f79056'];
|
||||
static aezeedWallet = ['#550271', '#530140'];
|
||||
|
||||
static createWallet = () => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
|
@ -65,6 +67,9 @@ export default class WalletGradient {
|
|||
case MultisigHDWallet.type:
|
||||
gradient = WalletGradient.multisigHdWallet;
|
||||
break;
|
||||
case HDAezeedWallet.type:
|
||||
gradient = WalletGradient.aezeedWallet;
|
||||
break;
|
||||
default:
|
||||
gradient = WalletGradient.defaultGradients;
|
||||
break;
|
||||
|
@ -119,6 +124,9 @@ export default class WalletGradient {
|
|||
case LightningCustodianWallet.type:
|
||||
gradient = WalletGradient.lightningCustodianWallet;
|
||||
break;
|
||||
case HDAezeedWallet.type:
|
||||
gradient = WalletGradient.aezeedWallet;
|
||||
break;
|
||||
default:
|
||||
gradient = WalletGradient.defaultGradients;
|
||||
break;
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
SegwitBech32Wallet,
|
||||
HDLegacyElectrumSeedP2PKHWallet,
|
||||
HDSegwitElectrumSeedP2WPKHWallet,
|
||||
HDAezeedWallet,
|
||||
MultisigHDWallet,
|
||||
} from '.';
|
||||
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
||||
|
@ -100,6 +101,7 @@ function WalletImport() {
|
|||
// 2. check if its HDLegacyP2PKHWallet (BIP44)
|
||||
// 3. check if its HDLegacyBreadwalletWallet (no BIP, just "m/0")
|
||||
// 3.1 check HD Electrum legacy
|
||||
// 3.2 check if its AEZEED
|
||||
// 4. check if its Segwit WIF (P2SH)
|
||||
// 5. check if its Legacy WIF
|
||||
// 6. check if its address (watch-only wallet)
|
||||
|
@ -234,6 +236,28 @@ function WalletImport() {
|
|||
}
|
||||
} catch (_) {}
|
||||
|
||||
// is it AEZEED?
|
||||
try {
|
||||
const aezeed = new HDAezeedWallet();
|
||||
aezeed.setSecret(importText);
|
||||
if (await aezeed.validateMnemonicAsync()) {
|
||||
// not fetching txs or balances, fuck it, yolo, life is too short
|
||||
return WalletImport._saveWallet(aezeed);
|
||||
} else {
|
||||
// there is a chance that a password is required
|
||||
if (await aezeed.mnemonicInvalidPassword()) {
|
||||
const password = await prompt(loc.wallets.enter_bip38_password, '', false);
|
||||
if (!password) {
|
||||
// no passord is basically cancel whole aezeed import process
|
||||
throw new Error(loc._.bad_password);
|
||||
}
|
||||
|
||||
const mnemonics = importText.split(':')[0];
|
||||
return WalletImport.processImportText(mnemonics + ':' + password);
|
||||
}
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
const hd2 = new HDSegwitP2SHWallet();
|
||||
hd2.setSecret(importText);
|
||||
if (hd2.validateMnemonic()) {
|
||||
|
|
141
class/wallets/hd-aezeed-wallet.js
Normal file
141
class/wallets/hd-aezeed-wallet.js
Normal file
|
@ -0,0 +1,141 @@
|
|||
import { AbstractHDElectrumWallet } from './abstract-hd-electrum-wallet';
|
||||
const bitcoin = require('bitcoinjs-lib');
|
||||
const { CipherSeed } = require('aezeed');
|
||||
|
||||
/**
|
||||
* AEZEED mnemonics support, which is used in LND
|
||||
* Support only BIP84 (native segwit) derivations
|
||||
*
|
||||
* @see https://github.com/lightningnetwork/lnd/tree/master/aezeed
|
||||
* @see https://github.com/bitcoinjs/aezeed
|
||||
* @see https://github.com/lightningnetwork/lnd/issues/4960
|
||||
* @see https://github.com/guggero/chantools/blob/master/doc/chantools_genimportscript.md
|
||||
* @see https://github.com/lightningnetwork/lnd/blob/master/keychain/derivation.go
|
||||
*/
|
||||
export class HDAezeedWallet extends AbstractHDElectrumWallet {
|
||||
static type = 'HDAezeedWallet';
|
||||
static typeReadable = 'HD Aezeed';
|
||||
|
||||
setSecret(newSecret) {
|
||||
this.secret = newSecret.trim();
|
||||
this.secret = this.secret.replace(/[^a-zA-Z0-9:]/g, ' ').replace(/\s+/g, ' ');
|
||||
return this;
|
||||
}
|
||||
|
||||
_getEntropyCached() {
|
||||
if (this._entropyHex) {
|
||||
// cache hit
|
||||
return Buffer.from(this._entropyHex, 'hex');
|
||||
} else {
|
||||
throw new Error('Entropy cache is not filled');
|
||||
}
|
||||
}
|
||||
|
||||
validateMnemonic(): boolean {
|
||||
throw new Error('Use validateMnemonicAsync()');
|
||||
}
|
||||
|
||||
async validateMnemonicAsync() {
|
||||
const [mnemonic3, password] = this.secret.split(':');
|
||||
try {
|
||||
const cipherSeed1 = await CipherSeed.fromMnemonic(mnemonic3, password || 'aezeed');
|
||||
this._entropyHex = cipherSeed1.entropy.toString('hex'); // save cache
|
||||
return !!cipherSeed1.entropy;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async mnemonicInvalidPassword() {
|
||||
const [mnemonic3, password] = this.secret.split(':');
|
||||
try {
|
||||
const cipherSeed1 = await CipherSeed.fromMnemonic(mnemonic3, password || 'aezeed');
|
||||
this._entropyHex = cipherSeed1.entropy.toString('hex'); // save cache
|
||||
} catch (error) {
|
||||
return error.message === 'Invalid Password';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async generate() {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
_getInternalAddressByIndex(index) {
|
||||
index = index * 1; // cast to int
|
||||
if (this.internal_addresses_cache[index]) return this.internal_addresses_cache[index]; // cache hit
|
||||
|
||||
if (!this._node1) {
|
||||
const root = bitcoin.bip32.fromSeed(this._getEntropyCached());
|
||||
const node = root.derivePath("m/84'/0'/0'");
|
||||
this._node1 = node.derive(1);
|
||||
}
|
||||
const address = bitcoin.payments.p2wpkh({
|
||||
pubkey: this._node1.derive(index).publicKey,
|
||||
}).address;
|
||||
|
||||
return (this.internal_addresses_cache[index] = address);
|
||||
}
|
||||
|
||||
_getExternalAddressByIndex(index) {
|
||||
index = index * 1; // cast to int
|
||||
if (this.external_addresses_cache[index]) return this.external_addresses_cache[index]; // cache hit
|
||||
|
||||
if (!this._node0) {
|
||||
const root = bitcoin.bip32.fromSeed(this._getEntropyCached());
|
||||
const node = root.derivePath("m/84'/0'/0'");
|
||||
this._node0 = node.derive(0);
|
||||
}
|
||||
const address = bitcoin.payments.p2wpkh({
|
||||
pubkey: this._node0.derive(index).publicKey,
|
||||
}).address;
|
||||
|
||||
return (this.external_addresses_cache[index] = address);
|
||||
}
|
||||
|
||||
_getWIFByIndex(internal, index) {
|
||||
if (!this.secret) return false;
|
||||
const root = bitcoin.bip32.fromSeed(this._getEntropyCached());
|
||||
const path = `m/84'/0'/0'/${internal ? 1 : 0}/${index}`;
|
||||
const child = root.derivePath(path);
|
||||
|
||||
return child.toWIF();
|
||||
}
|
||||
|
||||
_getNodePubkeyByIndex(node, index) {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
getIdentityPubkey() {
|
||||
const root = bitcoin.bip32.fromSeed(this._getEntropyCached());
|
||||
const node = root.derivePath("m/1017'/0'/6'/0/0");
|
||||
|
||||
return node.publicKey.toString('hex');
|
||||
}
|
||||
|
||||
// since its basically a bip84 wallet, we allow all other standard BIP84 features:
|
||||
|
||||
allowSend() {
|
||||
return true;
|
||||
}
|
||||
|
||||
allowBatchSend() {
|
||||
return true;
|
||||
}
|
||||
|
||||
allowSendMax() {
|
||||
return true;
|
||||
}
|
||||
|
||||
allowHodlHodlTrading() {
|
||||
return true;
|
||||
}
|
||||
|
||||
allowRBF() {
|
||||
return true;
|
||||
}
|
||||
|
||||
allowPayJoin() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -241,6 +241,8 @@ const WalletCarouselItem = ({ item, index, onPress, handleLongPress, isSelectedW
|
|||
<Text numberOfLines={1} style={[iStyles.latestTxTime, { color: colors.inverseForegroundColor }]}>
|
||||
{item.getBalance() !== 0 && item.getLatestTransactionTime() === 0
|
||||
? loc.wallets.pull_to_refresh
|
||||
: item.getTransactions().find(tx => tx.confirmations === 0)
|
||||
? loc.transactions.pending.toLowerCase()
|
||||
: transactionTimeToReadable(item.getLatestTransactionTime())}
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
|
|
|
@ -263,8 +263,6 @@ PODS:
|
|||
- React
|
||||
- react-native-fingerprint-scanner (6.0.0):
|
||||
- React
|
||||
- react-native-geolocation (2.0.2):
|
||||
- React
|
||||
- react-native-image-picker (3.1.4):
|
||||
- React-Core
|
||||
- react-native-is-catalyst (1.0.0):
|
||||
|
@ -450,7 +448,6 @@ DEPENDENCIES:
|
|||
- react-native-camera (from `../node_modules/react-native-camera`)
|
||||
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
|
||||
- react-native-fingerprint-scanner (from `../node_modules/react-native-fingerprint-scanner`)
|
||||
- "react-native-geolocation (from `../node_modules/@react-native-community/geolocation`)"
|
||||
- react-native-image-picker (from `../node_modules/react-native-image-picker`)
|
||||
- react-native-is-catalyst (from `../node_modules/react-native-is-catalyst`)
|
||||
- react-native-randombytes (from `../node_modules/react-native-randombytes`)
|
||||
|
@ -564,8 +561,6 @@ EXTERNAL SOURCES:
|
|||
:path: "../node_modules/react-native-document-picker"
|
||||
react-native-fingerprint-scanner:
|
||||
:path: "../node_modules/react-native-fingerprint-scanner"
|
||||
react-native-geolocation:
|
||||
:path: "../node_modules/@react-native-community/geolocation"
|
||||
react-native-image-picker:
|
||||
:path: "../node_modules/react-native-image-picker"
|
||||
react-native-is-catalyst:
|
||||
|
@ -702,7 +697,6 @@ SPEC CHECKSUMS:
|
|||
react-native-camera: 5c1fbfecf63b802b8ca4a71c60d30a71550fb348
|
||||
react-native-document-picker: c5752781fbc0c126c627c1549b037c139444a4cf
|
||||
react-native-fingerprint-scanner: c68136ca57e3704d7bdf5faa554ea535ce15b1d0
|
||||
react-native-geolocation: cbd9d6bd06bac411eed2671810f454d4908484a8
|
||||
react-native-image-picker: 248afb60a0c5a24153cb7c7483b257f30541323b
|
||||
react-native-is-catalyst: 52ee70e0123c82419dd4ce47dc4cc94b22467512
|
||||
react-native-randombytes: 991545e6eaaf700b4ee384c291ef3d572e0b2ca8
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
"filter_any": "أي عقد",
|
||||
"filter_buying": "الشراء",
|
||||
"filter_country_global": "العروض الشاملة",
|
||||
"filter_country_near": "بالقرب مني",
|
||||
"filter_currency": "العملة",
|
||||
"filter_detail": "التفاصيل",
|
||||
"filter_filters": "المرشحات",
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
"filter_any": "Всички",
|
||||
"filter_buying": "Купуване",
|
||||
"filter_country_global": "Всички оферти",
|
||||
"filter_country_near": "Наблизо",
|
||||
"filter_currency": "Валута",
|
||||
"filter_detail": "Детайли",
|
||||
"filter_filters": "Филтри",
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
"cont_title": "Els meus contractes",
|
||||
"filter_buying": "Comprant",
|
||||
"filter_country_global": "Ofertes globals",
|
||||
"filter_country_near": "A prop meu",
|
||||
"filter_currency": "Moneda",
|
||||
"filter_detail": "Detalls",
|
||||
"filter_filters": "Filtres",
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"filter_any": "Žádné",
|
||||
"filter_buying": "Nákup",
|
||||
"filter_country_global": "Globální nabídky",
|
||||
"filter_country_near": "Blízko mne",
|
||||
"filter_currency": "Měna",
|
||||
"filter_detail": "Detail",
|
||||
"filter_filters": "Filtry",
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"filter_any": "Jegliche",
|
||||
"filter_buying": "Kaufen",
|
||||
"filter_country_global": "Weltweite Angebote",
|
||||
"filter_country_near": "In meiner Nähe",
|
||||
"filter_currency": "Währung",
|
||||
"filter_detail": "Details",
|
||||
"filter_filters": "Filter",
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"filter_any": "Any",
|
||||
"filter_buying": "Buying",
|
||||
"filter_country_global": "Global Offers",
|
||||
"filter_country_near": "Near Me",
|
||||
"filter_currency": "Currency",
|
||||
"filter_detail": "Detail",
|
||||
"filter_filters": "Filters",
|
||||
|
@ -88,7 +87,7 @@
|
|||
"offer_promt_fiat": "How much {currency} do you want to buy?",
|
||||
"offer_promt_fiat_e": "For example, 100",
|
||||
"offer_window": "window",
|
||||
"p2p": "A p2p exchange"
|
||||
"p2p": "Buy Bitcoin on a p2p exchange"
|
||||
},
|
||||
"lnd": {
|
||||
"errorInvoiceExpired": "Invoice expired",
|
||||
|
@ -446,6 +445,7 @@
|
|||
"pull_to_refresh": "Pull to Refresh",
|
||||
"warning_do_not_disclose": "Warning! Do not disclose",
|
||||
"add_ln_wallet_first": "You must first add a Lightning wallet.",
|
||||
"identity_pubkey": "Identity Pubkey",
|
||||
"xpub_title": "Wallet XPUB"
|
||||
},
|
||||
"multisig": {
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"filter_any": "Cualquiera",
|
||||
"filter_buying": "Comprando",
|
||||
"filter_country_global": "Ofertas globales",
|
||||
"filter_country_near": "Cerca de mí",
|
||||
"filter_currency": "Divisa",
|
||||
"filter_detail": "Detalle",
|
||||
"filter_filters": "Filtros",
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
"filter_any": "Algo",
|
||||
"filter_buying": "Comprando",
|
||||
"filter_country_global": "Ofertas Globales",
|
||||
"filter_country_near": "Cerca de mí",
|
||||
"filter_currency": "Moneda",
|
||||
"filter_detail": "Detalle",
|
||||
"filter_filters": "Filtros",
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"filter_any": "همه",
|
||||
"filter_buying": "خرید",
|
||||
"filter_country_global": "پیشنهادهای جهانی",
|
||||
"filter_country_near": "نزدیک من",
|
||||
"filter_currency": "واحد پول",
|
||||
"filter_detail": "جزئیات",
|
||||
"filter_filters": "فیلترها",
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"filter_any": "Mikä tahansa",
|
||||
"filter_buying": "Ostaminen",
|
||||
"filter_country_global": "Maailmanlaajuiset tarjoukset",
|
||||
"filter_country_near": "Lähellä minua",
|
||||
"filter_currency": "Valuutta",
|
||||
"filter_detail": "Tiedot",
|
||||
"filter_filters": "Suodattimet",
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"filter_any": "Tous",
|
||||
"filter_buying": "Acheteur",
|
||||
"filter_country_global": "Offres internationales",
|
||||
"filter_country_near": "Près de moi",
|
||||
"filter_currency": "Devise",
|
||||
"filter_detail": "Détails",
|
||||
"filter_filters": "Filtres",
|
||||
|
|
|
@ -70,7 +70,6 @@
|
|||
"filter_any": "הכל",
|
||||
"filter_buying": "קנייה",
|
||||
"filter_country_global": "הצעות גלובליות",
|
||||
"filter_country_near": "לידי",
|
||||
"filter_currency": "מטבע",
|
||||
"filter_detail": "פרטים",
|
||||
"filter_filters": "מסננים",
|
||||
|
|
|
@ -67,7 +67,6 @@
|
|||
"filter_any": "Bármennyi",
|
||||
"filter_buying": "Vásárlás",
|
||||
"filter_country_global": "Ajánlatok világszerte",
|
||||
"filter_country_near": "Közelemben",
|
||||
"filter_currency": "Pénznem",
|
||||
"filter_detail": "Részletek",
|
||||
"filter_filters": "Szűrők",
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
"filter_any": "Apapun",
|
||||
"filter_buying": "Membeli",
|
||||
"filter_country_global": "Penawaran global",
|
||||
"filter_country_near": "Dekat saya",
|
||||
"filter_currency": "Mata uang",
|
||||
"filter_detail": "Perincian",
|
||||
"filter_filters": "Menyaring",
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
"cont_how": "Come pagare",
|
||||
"cont_st_completed": "Fatto!",
|
||||
"cont_title": "I miei contratti",
|
||||
"filter_country_near": "Vicino a me",
|
||||
"filter_currency": "Valuta",
|
||||
"filter_detail": "Dettaglio",
|
||||
"filter_filters": "Filtri",
|
||||
|
|
|
@ -68,7 +68,6 @@
|
|||
"filter_any": "すべて",
|
||||
"filter_buying": "買う",
|
||||
"filter_country_global": "グローバル・オファー",
|
||||
"filter_country_near": "近くで探す",
|
||||
"filter_currency": "通貨",
|
||||
"filter_detail": "詳細",
|
||||
"filter_filters": "フィルター",
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"filter_any": "ieder",
|
||||
"filter_buying": "Kopen",
|
||||
"filter_country_global": "Wereldwijd aanbod",
|
||||
"filter_country_near": "Dicht bij mij",
|
||||
"filter_currency": "Valuta",
|
||||
"filter_detail": "Detail",
|
||||
"filter_filters": "Filters",
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"filter_any": "Każdy",
|
||||
"filter_buying": "Kupno",
|
||||
"filter_country_global": "Oferty globalne",
|
||||
"filter_country_near": "Blisko mnie",
|
||||
"filter_currency": "Waluta",
|
||||
"filter_detail": "Szczegóły",
|
||||
"filter_filters": "Filtry",
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"filter_any": "Qualquer",
|
||||
"filter_buying": "Compra",
|
||||
"filter_country_global": "Ofertas globais",
|
||||
"filter_country_near": "Perto de mim",
|
||||
"filter_currency": "Moeda",
|
||||
"filter_detail": "Detalhe",
|
||||
"filter_filters": "Filtrar",
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
"filter_any": "Qualquer",
|
||||
"filter_buying": "Compra",
|
||||
"filter_country_global": "Ofertas globais",
|
||||
"filter_country_near": "Perto de mim",
|
||||
"filter_currency": "Moeda",
|
||||
"filter_detail": "Detalhe",
|
||||
"filter_filters": "Filtrar",
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"filter_any": "Все",
|
||||
"filter_buying": "Покупаю",
|
||||
"filter_country_global": "Глобальные",
|
||||
"filter_country_near": "Рядом со мной",
|
||||
"filter_currency": "Валюта",
|
||||
"filter_detail": "Все",
|
||||
"filter_filters": "Фильтры",
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
"cont_paid_q": "Naozaj chcete označiť tento kontrakt ako zaplatený?",
|
||||
"cont_st_completed": "Hotovo!",
|
||||
"cont_title": "Moje kontrakty",
|
||||
"filter_country_near": "Blízko mňa",
|
||||
"filter_currency": "Mena",
|
||||
"filter_detail": "Detail",
|
||||
"filter_filters": "Filtre",
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"filter_any": "Vse",
|
||||
"filter_buying": "Kupujem",
|
||||
"filter_country_global": "Globalne ponudbe",
|
||||
"filter_country_near": "Blizu mene",
|
||||
"filter_currency": "Valuta",
|
||||
"filter_detail": "Podrobno",
|
||||
"filter_filters": "Filtriraj",
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
"cont_st_completed": "Klart!",
|
||||
"cont_st_paid_enought": "Bitcoin hålls som säkerhet! Betala säljaren\nvia överenskommen betalmetod.",
|
||||
"cont_title": "Mina kontrakt",
|
||||
"filter_country_near": "Nära mig",
|
||||
"filter_currency": "Valuta",
|
||||
"filter_detail": "Detaljer",
|
||||
"filter_filters": "Filtrera",
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
"filter_any": "ใดๆ",
|
||||
"filter_buying": "กำลังซื้อ",
|
||||
"filter_country_global": "Global offers",
|
||||
"filter_country_near": "ใก้ลท่าน",
|
||||
"filter_currency": "สกุลเงิน",
|
||||
"filter_detail": "รายละเอียด",
|
||||
"filter_filters": "ตัวกรอง",
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
"cont_title": "我的合約",
|
||||
"filter_any": "任何",
|
||||
"filter_buying": "購買",
|
||||
"filter_country_near": "靠近我",
|
||||
"filter_currency": "貨幣",
|
||||
"filter_detail": "細節",
|
||||
"filter_iambuying": "我正在買比特幣",
|
||||
|
|
238
package-lock.json
generated
238
package-lock.json
generated
|
@ -6381,11 +6381,6 @@
|
|||
"integrity": "sha512-W/J0fNYVO01tioHjvYWQ9m6RgndVtbElzYozBq1ZPrHO/iCzlqoySHl4gO/fpCl9QEFjvJfjPgtPMTMlsoq5DQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@react-native-community/geolocation": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/geolocation/-/geolocation-2.0.2.tgz",
|
||||
"integrity": "sha512-tTNXRCgnhJBu79mulQwzabXRpDqfh/uaDqfHVpvF0nX4NTpolpy6mvTRiFg7eWFPGRArsnZz1EYp6rHfJWGgEA=="
|
||||
},
|
||||
"@react-native-community/masked-view": {
|
||||
"version": "0.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/masked-view/-/masked-view-0.1.10.tgz",
|
||||
|
@ -6999,6 +6994,15 @@
|
|||
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
|
||||
"dev": true
|
||||
},
|
||||
"aez": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/aez/-/aez-1.0.1.tgz",
|
||||
"integrity": "sha1-5O++9xE6khAvA3VL/fCDgMSw3sg=",
|
||||
"requires": {
|
||||
"blakejs": "^1.1.0",
|
||||
"safe-buffer": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
|
@ -8151,6 +8155,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"blakejs": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz",
|
||||
"integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U="
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
|
@ -9532,6 +9541,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"detox-recorder": {
|
||||
"version": "1.0.149",
|
||||
"resolved": "https://registry.npmjs.org/detox-recorder/-/detox-recorder-1.0.149.tgz",
|
||||
"integrity": "sha512-ycVtfSyXtG2PQOqhH57yHMXeVLZHM6dIK6hgL6UDOcD79zAuwKt4prdyzsPC7oaS6Zr4sXSZcd2DLQcbtm92KA==",
|
||||
"dev": true
|
||||
},
|
||||
"diff-sequences": {
|
||||
"version": "26.0.0",
|
||||
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.0.0.tgz",
|
||||
|
@ -10556,6 +10571,11 @@
|
|||
"integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
|
||||
"dev": true
|
||||
},
|
||||
"exit-on-epipe": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
|
||||
"integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw=="
|
||||
},
|
||||
"expand-brackets": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
|
||||
|
@ -15824,6 +15844,15 @@
|
|||
"object.assign": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"junderw-crc32c": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/junderw-crc32c/-/junderw-crc32c-1.2.0.tgz",
|
||||
"integrity": "sha512-tP0w5QOrunUS/XgsDBoZfw2jKNFhnUrdM96IXzuJtCyuXd19Hj47Hfd5+WFd81QDQFosiPffpc/jnSrZ35IV+A==",
|
||||
"requires": {
|
||||
"exit-on-epipe": "~1.0.1",
|
||||
"printj": "~1.1.0"
|
||||
}
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||
|
@ -16110,16 +16139,58 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
},
|
||||
"lodash._reinterpolate": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
||||
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
|
||||
},
|
||||
"lodash.frompairs": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.frompairs/-/lodash.frompairs-4.0.1.tgz",
|
||||
"integrity": "sha1-vE5SB/onV8E25XNhTpZkUGsrG9I="
|
||||
},
|
||||
"lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
|
||||
},
|
||||
"lodash.isstring": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
|
||||
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
|
||||
},
|
||||
"lodash.omit": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz",
|
||||
"integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA="
|
||||
},
|
||||
"lodash.pick": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
|
||||
"integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM="
|
||||
},
|
||||
"lodash.sortby": {
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
||||
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg="
|
||||
},
|
||||
"lodash.template": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
|
||||
"integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==",
|
||||
"requires": {
|
||||
"lodash._reinterpolate": "^3.0.0",
|
||||
"lodash.templatesettings": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"lodash.templatesettings": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz",
|
||||
"integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==",
|
||||
"requires": {
|
||||
"lodash._reinterpolate": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"lodash.throttle": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
||||
|
@ -18215,6 +18286,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"printj": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz",
|
||||
"integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ=="
|
||||
},
|
||||
"private": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
|
||||
|
@ -19242,23 +19318,68 @@
|
|||
"from": "git+https://github.com/BlueWallet/react-native-tooltip.git#d369e7ece09e4dec73873f1cfeac83e9d35294a6"
|
||||
},
|
||||
"react-native-vector-icons": {
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-6.6.0.tgz",
|
||||
"integrity": "sha512-MImKVx8JEvVVBnaShMr7/yTX4Y062JZMupht1T+IEgbqBj4aQeQ1z2SH4VHWKNtWtppk4kz9gYyUiMWqx6tNSw==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-7.1.0.tgz",
|
||||
"integrity": "sha512-V2a1zJ4i+kS8O4j183gIwX14St9AxxXabxwYpFBgRhvr2NDXyFcjHDEAgrOYYlt2W57e20aN1tBDU/I+wn9WtQ==",
|
||||
"requires": {
|
||||
"lodash": "^4.0.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"yargs": "^13.2.2"
|
||||
"lodash.frompairs": "^4.0.1",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"lodash.isstring": "^4.0.1",
|
||||
"lodash.omit": "^4.5.0",
|
||||
"lodash.pick": "^4.4.0",
|
||||
"lodash.template": "^4.5.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"yargs": "^15.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"cliui": {
|
||||
"ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
|
||||
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"requires": {
|
||||
"string-width": "^3.1.0",
|
||||
"strip-ansi": "^5.2.0",
|
||||
"wrap-ansi": "^5.1.0"
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
||||
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
|
||||
"requires": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^6.2.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"requires": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"get-caller-file": {
|
||||
|
@ -19266,52 +19387,87 @@
|
|||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"requires": {
|
||||
"p-locate": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"requires": {
|
||||
"p-limit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
|
||||
},
|
||||
"require-main-filename": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
|
||||
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
|
||||
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
|
||||
"requires": {
|
||||
"emoji-regex": "^7.0.1",
|
||||
"is-fullwidth-code-point": "^2.0.0",
|
||||
"strip-ansi": "^5.1.0"
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||
"requires": {
|
||||
"ansi-regex": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
|
||||
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.0",
|
||||
"string-width": "^3.0.0",
|
||||
"strip-ansi": "^5.0.0"
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"yargs": {
|
||||
"version": "13.3.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
|
||||
"integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
|
||||
"version": "15.4.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
|
||||
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
|
||||
"requires": {
|
||||
"cliui": "^5.0.0",
|
||||
"find-up": "^3.0.0",
|
||||
"cliui": "^6.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"find-up": "^4.1.0",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^2.0.0",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^3.0.0",
|
||||
"string-width": "^4.2.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^4.0.0",
|
||||
"yargs-parser": "^13.1.2"
|
||||
"yargs-parser": "^18.1.2"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "13.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
|
||||
"integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
|
||||
"version": "18.1.3",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
|
||||
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
|
@ -19989,6 +20145,10 @@
|
|||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"scryptsy": {
|
||||
"version": "file:blue_modules/scryptsy",
|
||||
"integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w=="
|
||||
},
|
||||
"secp256k1": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz",
|
||||
|
|
|
@ -70,7 +70,6 @@
|
|||
"@react-native-async-storage/async-storage": "1.13.3",
|
||||
"@react-native-community/blur": "3.6.0",
|
||||
"@react-native-community/clipboard": "1.5.1",
|
||||
"@react-native-community/geolocation": "2.0.2",
|
||||
"@react-native-community/masked-view": "0.1.10",
|
||||
"@react-native-community/push-notification-ios": "1.8.0",
|
||||
"@react-native-community/slider": "3.0.3",
|
||||
|
@ -79,11 +78,13 @@
|
|||
"@react-navigation/stack": "5.12.6",
|
||||
"@remobile/react-native-qrcode-local-image": "git+https://github.com/BlueWallet/react-native-qrcode-local-image.git",
|
||||
"@sentry/react-native": "1.9.0",
|
||||
"aez": "1.0.1",
|
||||
"amplitude-js": "7.3.3",
|
||||
"assert": "1.5.0",
|
||||
"base-x": "3.0.8",
|
||||
"bc-bech32": "file:blue_modules/bc-bech32",
|
||||
"bc-ur": "file:blue_modules/bc-ur",
|
||||
"scryptsy": "file:blue_modules/scryptsy",
|
||||
"bech32": "1.1.4",
|
||||
"bignumber.js": "9.0.1",
|
||||
"bip21": "2.0.3",
|
||||
|
@ -107,6 +108,7 @@
|
|||
"eslint-plugin-standard": "4.0.2",
|
||||
"events": "1.1.1",
|
||||
"frisbee": "3.1.4",
|
||||
"junderw-crc32c": "1.2.0",
|
||||
"lottie-ios": "3.1.8",
|
||||
"lottie-react-native": "3.5.0",
|
||||
"metro-react-native-babel-preset": "0.63.0",
|
||||
|
@ -158,7 +160,7 @@
|
|||
"react-native-svg": "12.1.0",
|
||||
"react-native-tcp-socket": "3.7.1",
|
||||
"react-native-tooltip": "git+https://github.com/BlueWallet/react-native-tooltip.git#d369e7ece09e4dec73873f1cfeac83e9d35294a6",
|
||||
"react-native-vector-icons": "6.6.0",
|
||||
"react-native-vector-icons": "7.1.0",
|
||||
"react-native-watch-connectivity": "1.0.3",
|
||||
"react-native-webview": "11.0.0",
|
||||
"react-native-widget-center": "git+https://github.com/BlueWallet/react-native-widget-center.git#e2e9a9038b76d096bf929a87105a97a0a7095001",
|
||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||
import { ScrollView, View, StyleSheet } from 'react-native';
|
||||
import { BlueSpacing20, SafeBlueArea, BlueCard, BlueText, BlueLoading } from '../BlueComponents';
|
||||
import navigationStyle from '../components/navigationStyle';
|
||||
import { SegwitP2SHWallet, LegacyWallet, HDSegwitP2SHWallet, HDSegwitBech32Wallet } from '../class';
|
||||
import { SegwitP2SHWallet, LegacyWallet, HDSegwitP2SHWallet, HDSegwitBech32Wallet, HDAezeedWallet } from '../class';
|
||||
import { BlueCurrentTheme } from '../components/themes';
|
||||
const bitcoin = require('bitcoinjs-lib');
|
||||
const BlueCrypto = require('react-native-blue-crypto');
|
||||
|
@ -63,7 +63,14 @@ export default class Selftest extends Component {
|
|||
// skipping RN-specific test'
|
||||
}
|
||||
|
||||
//
|
||||
if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
|
||||
const aezeed = new HDAezeedWallet();
|
||||
aezeed.setSecret('abstract rhythm weird food attract treat mosquito sight royal actor surround ride strike remove guilt catch filter summer mushroom protect poverty cruel chaos pattern');
|
||||
assertStrictEqual(await aezeed.validateMnemonicAsync(), true, 'Aezeed failed');
|
||||
assertStrictEqual(aezeed._getExternalAddressByIndex(0), 'bc1qdjj7lhj9lnjye7xq3dzv3r4z0cta294xy78txn', 'Aezeed failed');
|
||||
} else {
|
||||
// skipping RN-specific test
|
||||
}
|
||||
|
||||
let l = new LegacyWallet();
|
||||
l.setSecret('L4ccWrPMmFDZw4kzAKFqJNxgHANjdy6b7YKNXMwB4xac4FLF3Tov');
|
||||
|
|
|
@ -694,7 +694,7 @@ export default class SendDetails extends Component {
|
|||
|
||||
onWalletSelect = wallet => {
|
||||
const changeWallet = () => {
|
||||
this.setState({ fromWallet: wallet, utxo: null }, () => {
|
||||
this.setState({ fromWallet: wallet, utxo: null, changeAddress: null }, () => {
|
||||
this.renderNavigationHeader();
|
||||
this.context.setSelectedWallet(wallet.getID());
|
||||
this.props.navigation.pop();
|
||||
|
|
|
@ -24,7 +24,15 @@ import { HDLegacyP2PKHWallet } from '../../class/wallets/hd-legacy-p2pkh-wallet'
|
|||
import { HDSegwitP2SHWallet } from '../../class/wallets/hd-segwit-p2sh-wallet';
|
||||
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
||||
import Biometric from '../../class/biometrics';
|
||||
import { HDSegwitBech32Wallet, SegwitP2SHWallet, LegacyWallet, SegwitBech32Wallet, WatchOnlyWallet, MultisigHDWallet } from '../../class';
|
||||
import {
|
||||
HDSegwitBech32Wallet,
|
||||
SegwitP2SHWallet,
|
||||
LegacyWallet,
|
||||
SegwitBech32Wallet,
|
||||
WatchOnlyWallet,
|
||||
MultisigHDWallet,
|
||||
HDAezeedWallet,
|
||||
} from '../../class';
|
||||
import { ScrollView } from 'react-native-gesture-handler';
|
||||
import loc from '../../loc';
|
||||
import { useTheme, useRoute, useNavigation } from '@react-navigation/native';
|
||||
|
@ -457,6 +465,13 @@ const WalletDetails = () => {
|
|||
<BlueText>{wallet.getBaseURI()}</BlueText>
|
||||
</>
|
||||
)}
|
||||
|
||||
{wallet.type === HDAezeedWallet.type && (
|
||||
<>
|
||||
<Text style={[styles.textLabel1, stylesHook.textLabel1]}>{loc.wallets.identity_pubkey.toLowerCase()}</Text>
|
||||
<BlueText>{wallet.getIdentityPubkey()}</BlueText>
|
||||
</>
|
||||
)}
|
||||
<>
|
||||
<Text onPress={exportInternals} style={[styles.textLabel2, stylesHook.textLabel2]}>
|
||||
{loc.transactions.list_title.toLowerCase()}
|
||||
|
|
|
@ -20,7 +20,6 @@ import {
|
|||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import Geolocation from '@react-native-community/geolocation';
|
||||
|
||||
import { BlueButtonLink, SafeBlueArea } from '../../BlueComponents';
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
|
@ -37,7 +36,6 @@ const METHOD_ANY = '_any';
|
|||
|
||||
const HodlHodlListSections = { OFFERS: 'OFFERS' };
|
||||
const windowHeight = Dimensions.get('window').height;
|
||||
Geolocation.setRNConfiguration({ authorizationLevel: 'whenInUse' });
|
||||
|
||||
export default class HodlHodl extends Component {
|
||||
static contextType = BlueStorageContext;
|
||||
|
@ -62,7 +60,6 @@ export default class HodlHodl extends Component {
|
|||
currencies: [], // list of hodlhodl supported currencies. filled later via api
|
||||
methods: [], // list of hodlhodl payment methods. filled later via api
|
||||
country: HodlHodlApi.FILTERS_COUNTRY_VALUE_GLOBAL, // country currently selected by user to display orders on screen. this is country code
|
||||
myCountryCode: HodlHodlApi.FILTERS_COUNTRY_VALUE_GLOBAL, // current user's country. filled later, via geoip api
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -123,33 +120,6 @@ export default class HodlHodl extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
async fetchMyCountry() {
|
||||
return new Promise(resolve => {
|
||||
Geolocation.getCurrentPosition(
|
||||
async _position => {
|
||||
const myCountryCode = await this.state.HodlApi.getMyCountryCode();
|
||||
if (myCountryCode === 'US') {
|
||||
alert('This service is currently not available in your country.');
|
||||
this.props.navigation.goBack();
|
||||
} else {
|
||||
this.setState(
|
||||
{
|
||||
myCountryCode,
|
||||
country: myCountryCode, // we start with orders from current country
|
||||
},
|
||||
resolve(),
|
||||
);
|
||||
}
|
||||
},
|
||||
_error =>
|
||||
resolve(
|
||||
this.setState({ myCountryCode: HodlHodlApi.FILTERS_COUNTRY_VALUE_GLOBAL, cuntry: HodlHodlApi.FILTERS_COUNTRY_VALUE_GLOBAL }),
|
||||
),
|
||||
{ enableHighAccuracy: false, timeout: 20000, maximumAge: 1000 },
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches all countries from API and sets them to state
|
||||
*
|
||||
|
@ -213,7 +183,6 @@ export default class HodlHodl extends Component {
|
|||
});
|
||||
|
||||
try {
|
||||
await this.fetchMyCountry();
|
||||
await this.fetchOffers();
|
||||
} catch (Error) {
|
||||
alert(Error.message);
|
||||
|
@ -345,8 +314,6 @@ export default class HodlHodl extends Component {
|
|||
}
|
||||
|
||||
getNativeCountryName() {
|
||||
if (this.state.country === this.state.myCountryCode && this.state.country !== HodlHodlApi.FILTERS_COUNTRY_VALUE_GLOBAL)
|
||||
return loc.hodl.filter_country_near;
|
||||
for (const c of this.state.countries) {
|
||||
if (c.code === this.state.country) return c.native_name;
|
||||
}
|
||||
|
|
|
@ -149,7 +149,9 @@ const ReorderWallets = () => {
|
|||
{loc.wallets.list_latest_transaction}
|
||||
</Text>
|
||||
<Text numberOfLines={1} style={styles.latestTxValue}>
|
||||
{transactionTimeToReadable(item.getLatestTransactionTime())}
|
||||
{item.getTransactions().find(tx => tx.confirmations === 0)
|
||||
? loc.transactions.pending.toLowerCase()
|
||||
: transactionTimeToReadable(item.getLatestTransactionTime())}
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</View>
|
||||
|
|
|
@ -13,7 +13,7 @@ import loc, { formatBalance, transactionTimeToReadable } from '../../loc';
|
|||
import { MultisigHDWallet } from '../../class';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
|
||||
const SelectWallet = ({ navigation }) => {
|
||||
const SelectWallet = () => {
|
||||
const { chainType, onWalletSelect, availableWallets } = useRoute().params;
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const { wallets } = useContext(BlueStorageContext);
|
||||
|
@ -101,7 +101,7 @@ const SelectWallet = ({ navigation }) => {
|
|||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
ReactNativeHapticFeedback.trigger('selection', { ignoreAndroidSystemSettings: false });
|
||||
onWalletSelect(item, { navigation });
|
||||
onWalletSelect(item);
|
||||
}}
|
||||
>
|
||||
<View shadowOpacity={40 / 100} shadowOffset={{ width: 0, height: 0 }} shadowRadius={5} style={styles.itemRoot}>
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('BlueWallet UI Tests', () => {
|
|||
process.env.TRAVIS && require('fs').writeFileSync(lockFile, '1');
|
||||
});
|
||||
|
||||
it('can create wallet, reload app and it persists. then go to receive screen, set custom amount and label.', async () => {
|
||||
it('can create wallet, reload app and it persists. then go to receive screen, set custom amount and label. Dismiss modal and go to WalletsList.', async () => {
|
||||
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName);
|
||||
if (process.env.TRAVIS) {
|
||||
if (require('fs').existsSync(lockFile))
|
||||
|
@ -47,7 +47,11 @@ describe('BlueWallet UI Tests', () => {
|
|||
await element(by.id('cr34t3d')).tap();
|
||||
await element(by.id('ReceiveButton')).tap();
|
||||
await element(by.text('Yes, I have')).tap();
|
||||
await element(by.text(`No, and don't ask me again`)).tap();
|
||||
try {
|
||||
// in case emulator has no google services and doesnt support pushes
|
||||
// we just dont show this popup
|
||||
await element(by.text(`No, and don't ask me again`)).tap();
|
||||
} catch (_) {}
|
||||
await yo('BitcoinAddressQRCodeContainer');
|
||||
await yo('BlueCopyTextToClipboard');
|
||||
await element(by.id('SetCustomAmountButton')).tap();
|
||||
|
@ -508,6 +512,26 @@ describe('BlueWallet UI Tests', () => {
|
|||
'0.00030666 BTC',
|
||||
);
|
||||
|
||||
await element(by.id('ReceiveButton')).tap();
|
||||
try {
|
||||
// in case emulator has no google services and doesnt support pushes
|
||||
// we just dont show this popup
|
||||
await element(by.text(`No, and don't ask me again`)).tap();
|
||||
} catch (_) {}
|
||||
await expect(element(by.id('BitcoinAddressQRCodeContainer'))).toBeVisible();
|
||||
await expect(element(by.text('bc1qtc9zquvq7lgq87kzsgltvv4etwm9uxphfkvkay'))).toBeVisible();
|
||||
await element(by.id('SetCustomAmountButton')).tap();
|
||||
await element(by.id('BitcoinAmountInput')).typeText('1');
|
||||
await element(by.id('CustomAmountDescription')).typeText('Test');
|
||||
await element(by.id('CustomAmountSaveButton')).tap();
|
||||
await expect(element(by.text('1 BTC'))).toBeVisible();
|
||||
await expect(element(by.text('Test'))).toBeVisible();
|
||||
await expect(element(by.id('BitcoinAddressQRCodeContainer'))).toBeVisible();
|
||||
|
||||
|
||||
await expect(element(by.text('bitcoin:bc1qtc9zquvq7lgq87kzsgltvv4etwm9uxphfkvkay?amount=1&label=Test'))).toBeVisible();
|
||||
await device.pressBack();
|
||||
|
||||
await element(by.id('SendButton')).tap();
|
||||
await element(by.text('OK')).tap();
|
||||
|
||||
|
|
|
@ -106,9 +106,6 @@ describe.skip('HodlHodl API', function () {
|
|||
assert.ok(countries[0].native_name);
|
||||
assert.ok(countries[0].currency_code);
|
||||
assert.ok(countries[0].currency_name);
|
||||
|
||||
const countryCode = await Hodl.getMyCountryCode();
|
||||
assert.strictEqual(countryCode.length, 2);
|
||||
});
|
||||
|
||||
it('can get offers', async () => {
|
||||
|
|
70
tests/unit/hd-aezeed.test.js
Normal file
70
tests/unit/hd-aezeed.test.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* global describe, it */
|
||||
import { HDAezeedWallet } from '../../class';
|
||||
const assert = require('assert');
|
||||
|
||||
describe('HDAezeedWallet', () => {
|
||||
it('can import mnemonics and generate addresses and WIFs', async function () {
|
||||
const aezeed = new HDAezeedWallet();
|
||||
|
||||
aezeed.setSecret('bs');
|
||||
assert.ok(!(await aezeed.validateMnemonicAsync()));
|
||||
assert.ok(!(await aezeed.mnemonicInvalidPassword()));
|
||||
|
||||
// correct pass:
|
||||
aezeed.setSecret(
|
||||
'able mix price funny host express lawsuit congress antique float pig exchange vapor drip wide cup style apple tumble verb fix blush tongue market:strongPassword',
|
||||
);
|
||||
assert.ok(await aezeed.validateMnemonicAsync());
|
||||
assert.ok(!(await aezeed.mnemonicInvalidPassword()));
|
||||
|
||||
// no pass but its required:
|
||||
aezeed.setSecret(
|
||||
'able mix price funny host express lawsuit congress antique float pig exchange vapor drip wide cup style apple tumble verb fix blush tongue market',
|
||||
);
|
||||
assert.ok(!(await aezeed.validateMnemonicAsync()));
|
||||
assert.ok(await aezeed.mnemonicInvalidPassword());
|
||||
|
||||
// wrong pass:
|
||||
aezeed.setSecret(
|
||||
'able mix price funny host express lawsuit congress antique float pig exchange vapor drip wide cup style apple tumble verb fix blush tongue market:badpassword',
|
||||
);
|
||||
assert.ok(!(await aezeed.validateMnemonicAsync()));
|
||||
assert.ok(await aezeed.mnemonicInvalidPassword());
|
||||
|
||||
aezeed.setSecret(
|
||||
'able concert slush lend olive cost wagon dawn board robot park snap dignity churn fiction quote shrimp hammer wing jump immune skill sunset west',
|
||||
);
|
||||
assert.ok(await aezeed.validateMnemonicAsync());
|
||||
assert.ok(!(await aezeed.mnemonicInvalidPassword()));
|
||||
|
||||
aezeed.setSecret(
|
||||
'abstract rhythm weird food attract treat mosquito sight royal actor surround ride strike remove guilt catch filter summer mushroom protect poverty cruel chaos pattern',
|
||||
);
|
||||
assert.ok(await aezeed.validateMnemonicAsync());
|
||||
assert.ok(!(await aezeed.mnemonicInvalidPassword()));
|
||||
|
||||
assert.strictEqual(
|
||||
aezeed.getXpub(),
|
||||
'zpub6rrqwqM3aF1Jdz6y5Zw18RTppHbZQeQpsrSyf3E2uibcrsEeZAbm5MX41Nq4XBF7HbCvRVASHLzRkFsg6sMgakcceWzJazZH7SaVPBoXzDQ',
|
||||
);
|
||||
|
||||
let address = aezeed._getExternalAddressByIndex(0);
|
||||
assert.strictEqual(address, 'bc1qdjj7lhj9lnjye7xq3dzv3r4z0cta294xy78txn');
|
||||
assert.ok(aezeed.getAllExternalAddresses().includes('bc1qdjj7lhj9lnjye7xq3dzv3r4z0cta294xy78txn'));
|
||||
|
||||
address = aezeed._getExternalAddressByIndex(1);
|
||||
assert.strictEqual(address, 'bc1qswr3s4fylskqn9vemef8l28qukshuagsjz3wpe');
|
||||
assert.ok(aezeed.getAllExternalAddresses().includes('bc1qswr3s4fylskqn9vemef8l28qukshuagsjz3wpe'));
|
||||
|
||||
address = aezeed._getInternalAddressByIndex(0);
|
||||
assert.strictEqual(address, 'bc1qzyjq8sjj56n8v9fgw5klsc8sq8yuy0jx03hzzp');
|
||||
|
||||
let wif = aezeed._getExternalWIFByIndex(0);
|
||||
assert.strictEqual(wif, 'KxtkgprHVXCcgzRetDt3JnNuRApgzQyRrvAuwiE1yFPjmYnWh6rH');
|
||||
|
||||
wif = aezeed._getInternalWIFByIndex(0);
|
||||
assert.strictEqual(wif, 'L1dewhNXkVMB3JdoXYRikbz6g4CbaMGfSqSXSrmTkk5PvzmEgpdT');
|
||||
|
||||
assert.strictEqual(aezeed.getIdentityPubkey(), '0384b9a7158320e828280075224af324931ca9d6de4334f724dbb553ffee447164');
|
||||
});
|
||||
});
|
Loading…
Add table
Reference in a new issue