Merge remote-tracking branch 'origin/master' into ccfix

This commit is contained in:
Overtorment 2021-01-29 19:14:55 +00:00
commit 7736b5278c
68 changed files with 3407 additions and 508 deletions

24
FAQ.md Normal file
View 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 doesnt 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.

View 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.

View file

@ -0,0 +1,2 @@
# aezeed
A package for encoding, decoding, and generating mnemonics of the aezeed specification. (WIP)

View 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
View 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;
}

View 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
View file

@ -0,0 +1,3 @@
/// <reference types="node" />
export declare function mnemonicFromBytes(bytes: Buffer): string;
export declare function mnemonicToBytes(mnemonic: string): Buffer;

File diff suppressed because it is too large Load diff

8
blue_modules/aezeed/src/params.d.ts vendored Normal file
View 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;

View 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;

View file

@ -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')

View file

@ -1,3 +0,0 @@
test/
.gitignore
.min-wd

View file

@ -1,70 +0,0 @@
scryptsy
========
[![build status](https://secure.travis-ci.org/cryptocoinjs/scryptsy.svg)](http://travis-ci.org/cryptocoinjs/scryptsy)
[![Coverage Status](https://img.shields.io/coveralls/cryptocoinjs/scryptsy.svg)](https://coveralls.io/r/cryptocoinjs/scryptsy)
[![Version](http://img.shields.io/npm/v/scryptsy.svg)](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

View file

@ -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

View file

@ -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"
}
}

View file

@ -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.

View 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.

View file

@ -0,0 +1,157 @@
scryptsy
========
[![build status](https://secure.travis-ci.org/cryptocoinjs/scryptsy.svg)](http://travis-ci.org/cryptocoinjs/scryptsy)
[![Coverage Status](https://img.shields.io/coveralls/cryptocoinjs/scryptsy.svg)](https://coveralls.io/r/cryptocoinjs/scryptsy)
[![Version](http://img.shields.io/npm/v/scryptsy.svg)](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

View file

@ -0,0 +1,3 @@
const scrypt = require('./scryptSync')
scrypt.async = require('./scrypt')
module.exports = scrypt

View 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

View 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

View 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
}

View 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"
}

View file

@ -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);

View file

@ -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());

View file

@ -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';

View file

@ -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;

View file

@ -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()) {

View 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;
}
}

View file

@ -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>

View file

@ -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

View file

@ -53,7 +53,6 @@
"filter_any": "أي عقد",
"filter_buying": "الشراء",
"filter_country_global": "العروض الشاملة",
"filter_country_near": "بالقرب مني",
"filter_currency": "العملة",
"filter_detail": "التفاصيل",
"filter_filters": "المرشحات",

View file

@ -55,7 +55,6 @@
"filter_any": "Всички",
"filter_buying": "Купуване",
"filter_country_global": "Всички оферти",
"filter_country_near": "Наблизо",
"filter_currency": "Валута",
"filter_detail": "Детайли",
"filter_filters": "Филтри",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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": {

View file

@ -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",

View file

@ -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",

View file

@ -61,7 +61,6 @@
"filter_any": "همه",
"filter_buying": "خرید",
"filter_country_global": "پیشنهادهای جهانی",
"filter_country_near": "نزدیک من",
"filter_currency": "واحد پول",
"filter_detail": "جزئیات",
"filter_filters": "فیلترها",

View file

@ -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",

View file

@ -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",

View file

@ -70,7 +70,6 @@
"filter_any": "הכל",
"filter_buying": "קנייה",
"filter_country_global": "הצעות גלובליות",
"filter_country_near": "לידי",
"filter_currency": "מטבע",
"filter_detail": "פרטים",
"filter_filters": "מסננים",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -68,7 +68,6 @@
"filter_any": "すべて",
"filter_buying": "買う",
"filter_country_global": "グローバル・オファー",
"filter_country_near": "近くで探す",
"filter_currency": "通貨",
"filter_detail": "詳細",
"filter_filters": "フィルター",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -61,7 +61,6 @@
"filter_any": "Все",
"filter_buying": "Покупаю",
"filter_country_global": "Глобальные",
"filter_country_near": "Рядом со мной",
"filter_currency": "Валюта",
"filter_detail": "Все",
"filter_filters": "Фильтры",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -51,7 +51,6 @@
"filter_any": "ใดๆ",
"filter_buying": "กำลังซื้อ",
"filter_country_global": "Global offers",
"filter_country_near": "ใก้ลท่าน",
"filter_currency": "สกุลเงิน",
"filter_detail": "รายละเอียด",
"filter_filters": "ตัวกรอง",

View file

@ -39,7 +39,6 @@
"cont_title": "我的合約",
"filter_any": "任何",
"filter_buying": "購買",
"filter_country_near": "靠近我",
"filter_currency": "貨幣",
"filter_detail": "細節",
"filter_iambuying": "我正在買比特幣",

238
package-lock.json generated
View file

@ -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",

View file

@ -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",

View file

@ -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');

View file

@ -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();

View file

@ -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()}

View file

@ -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;
}

View file

@ -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>

View file

@ -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}>

View file

@ -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();

View file

@ -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 () => {

View 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');
});
});