Marcos Rodriguez Vélez
6 years ago
116 changed files with 5353 additions and 16780 deletions
@ -1,3 +1,3 @@ |
|||
{ |
|||
"presets": ["module:metro-react-native-babel-preset"] |
|||
} |
|||
} |
|||
|
@ -0,0 +1,6 @@ |
|||
|
|||
[android] |
|||
target = Google Inc.:Google APIs:23 |
|||
|
|||
[maven_repositories] |
|||
central = https://repo1.maven.org/maven2 |
@ -0,0 +1 @@ |
|||
*.pbxproj -text |
@ -1 +1 @@ |
|||
{} |
|||
{} |
@ -0,0 +1,195 @@ |
|||
import { AsyncStorage } from 'react-native'; |
|||
const ElectrumClient = require('electrum-client'); |
|||
let bitcoin = require('bitcoinjs-lib'); |
|||
let reverse = require('buffer-reverse'); |
|||
|
|||
const storageKey = 'ELECTRUM_PEERS'; |
|||
const defaultPeer = { host: 'electrum.coinucopia.io', tcp: 50001 }; |
|||
|
|||
let mainClient = false; |
|||
let mainConnected = false; |
|||
|
|||
async function connectMain() { |
|||
let usingPeer = await getRandomHardcodedPeer(); |
|||
try { |
|||
console.log('begin connection:', JSON.stringify(usingPeer)); |
|||
mainClient = new ElectrumClient(usingPeer.tcp, usingPeer.host, 'tcp'); |
|||
await mainClient.connect(); |
|||
const ver = await mainClient.server_version('2.7.11', '1.2'); |
|||
console.log('connected to ', ver); |
|||
let peers = await mainClient.serverPeers_subscribe(); |
|||
if (peers && peers.length > 0) { |
|||
mainConnected = true; |
|||
AsyncStorage.setItem(storageKey, JSON.stringify(peers)); |
|||
} |
|||
} catch (e) { |
|||
mainConnected = false; |
|||
console.log('bad connection:', JSON.stringify(usingPeer)); |
|||
} |
|||
|
|||
if (!mainConnected) { |
|||
console.log('retry'); |
|||
setTimeout(connectMain, 5000); |
|||
} |
|||
} |
|||
|
|||
connectMain(); |
|||
|
|||
/** |
|||
* Returns random hardcoded electrum server guaranteed to work |
|||
* at the time of writing. |
|||
* |
|||
* @returns {Promise<{tcp, host}|*>} |
|||
*/ |
|||
async function getRandomHardcodedPeer() { |
|||
let hardcodedPeers = [ |
|||
{ host: 'node.ispol.sk', tcp: '50001' }, |
|||
{ host: 'electrum.vom-stausee.de', tcp: '50001' }, |
|||
{ host: 'orannis.com', tcp: '50001' }, |
|||
{ host: '139.162.14.142', tcp: '50001' }, |
|||
{ host: 'daedalus.bauerj.eu', tcp: '50001' }, |
|||
{ host: 'electrum.eff.ro', tcp: '50001' }, |
|||
{ host: 'electrum.anduck.net', tcp: '50001' }, |
|||
{ host: 'mooo.not.fyi', tcp: '50011' }, |
|||
{ host: 'electrum.coinucopia.io', tcp: '50001' }, |
|||
]; |
|||
return hardcodedPeers[(hardcodedPeers.length * Math.random()) | 0]; |
|||
} |
|||
|
|||
/** |
|||
* Returns random electrum server out of list of servers |
|||
* previous electrum server told us. Nearly half of them is |
|||
* usually offline. |
|||
* Not used for now. |
|||
* |
|||
* @returns {Promise<{tcp: number, host: string}>} |
|||
*/ |
|||
// eslint-disable-next-line
|
|||
async function getRandomDynamicPeer() { |
|||
try { |
|||
let peers = JSON.parse(await AsyncStorage.getItem(storageKey)); |
|||
peers = peers.sort(() => Math.random() - 0.5); // shuffle
|
|||
for (let peer of peers) { |
|||
let ret = {}; |
|||
ret.host = peer[1]; |
|||
for (let item of peer[2]) { |
|||
if (item.startsWith('t')) { |
|||
ret.tcp = item.replace('t', ''); |
|||
} |
|||
} |
|||
if (ret.host && ret.tcp) return ret; |
|||
} |
|||
|
|||
return defaultPeer; // failed to find random client, using default
|
|||
} catch (_) { |
|||
return defaultPeer; // smth went wrong, using default
|
|||
} |
|||
} |
|||
|
|||
/** |
|||
* |
|||
* @param address {String} |
|||
* @returns {Promise<Object>} |
|||
*/ |
|||
async function getBalanceByAddress(address) { |
|||
if (!mainClient) throw new Error('Electrum client is not connected'); |
|||
let script = bitcoin.address.toOutputScript(address); |
|||
let hash = bitcoin.crypto.sha256(script); |
|||
let reversedHash = Buffer.from(reverse(hash)); |
|||
let balance = await mainClient.blockchainScripthash_getBalance(reversedHash.toString('hex')); |
|||
balance.addr = address; |
|||
return balance; |
|||
} |
|||
|
|||
/** |
|||
* |
|||
* @param address {String} |
|||
* @returns {Promise<Array>} |
|||
*/ |
|||
async function getTransactionsByAddress(address) { |
|||
if (!mainClient) throw new Error('Electrum client is not connected'); |
|||
let script = bitcoin.address.toOutputScript(address); |
|||
let hash = bitcoin.crypto.sha256(script); |
|||
let reversedHash = Buffer.from(reverse(hash)); |
|||
let history = await mainClient.blockchainScripthash_getHistory(reversedHash.toString('hex')); |
|||
return history; |
|||
} |
|||
|
|||
/** |
|||
* |
|||
* @param addresses {Array} |
|||
* @returns {Promise<{balance: number, unconfirmed_balance: number}>} |
|||
*/ |
|||
async function multiGetBalanceByAddress(addresses) { |
|||
if (!mainClient) throw new Error('Electrum client is not connected'); |
|||
let balance = 0; |
|||
let unconfirmedBalance = 0; |
|||
for (let addr of addresses) { |
|||
let b = await getBalanceByAddress(addr); |
|||
|
|||
balance += b.confirmed; |
|||
unconfirmedBalance += b.unconfirmed_balance; |
|||
} |
|||
|
|||
return { balance, unconfirmed_balance: unconfirmedBalance }; |
|||
} |
|||
|
|||
/** |
|||
* Simple waiter till `mainConnected` becomes true (which means |
|||
* it Electrum was connected in other function), or timeout 30 sec. |
|||
* |
|||
* |
|||
* @returns {Promise<Promise<*> | Promise<*>>} |
|||
*/ |
|||
async function waitTillConnected() { |
|||
let waitTillConnectedInterval = false; |
|||
let retriesCounter = 0; |
|||
return new Promise(function(resolve, reject) { |
|||
waitTillConnectedInterval = setInterval(() => { |
|||
if (mainConnected) { |
|||
clearInterval(waitTillConnectedInterval); |
|||
resolve(true); |
|||
} |
|||
if (retriesCounter++ >= 30) { |
|||
clearInterval(waitTillConnectedInterval); |
|||
reject(new Error('Waiting for Electrum connection timeout')); |
|||
} |
|||
}, 1000); |
|||
}); |
|||
} |
|||
|
|||
module.exports.getBalanceByAddress = getBalanceByAddress; |
|||
module.exports.getTransactionsByAddress = getTransactionsByAddress; |
|||
module.exports.multiGetBalanceByAddress = multiGetBalanceByAddress; |
|||
module.exports.waitTillConnected = waitTillConnected; |
|||
|
|||
module.exports.forceDisconnect = () => { |
|||
mainClient.keepAlive = () => {}; // dirty hack to make it stop reconnecting
|
|||
mainClient.reconnect = () => {}; // dirty hack to make it stop reconnecting
|
|||
mainClient.close(); |
|||
}; |
|||
|
|||
/* |
|||
|
|||
|
|||
|
|||
let addr4elect = 'bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej'; |
|||
let script = bitcoin.address.toOutputScript(addr4elect); |
|||
let hash = bitcoin.crypto.sha256(script); |
|||
let reversedHash = Buffer.from(hash.reverse()); |
|||
console.log(addr4elect, ' maps to ', reversedHash.toString('hex')); |
|||
console.log(await mainClient.blockchainScripthash_getBalance(reversedHash.toString('hex'))); |
|||
|
|||
addr4elect = '1BWwXJH3q6PRsizBkSGm2Uw4Sz1urZ5sCj'; |
|||
script = bitcoin.address.toOutputScript(addr4elect); |
|||
hash = bitcoin.crypto.sha256(script); |
|||
reversedHash = Buffer.from(hash.reverse()); |
|||
console.log(addr4elect, ' maps to ', reversedHash.toString('hex')); |
|||
console.log(await mainClient.blockchainScripthash_getBalance(reversedHash.toString('hex'))); |
|||
|
|||
// let peers = await mainClient.serverPeers_subscribe();
|
|||
// console.log(peers);
|
|||
mainClient.keepAlive = () => {}; // dirty hack to make it stop reconnecting
|
|||
mainClient.reconnect = () => {}; // dirty hack to make it stop reconnecting
|
|||
mainClient.close(); |
|||
// setTimeout(()=>process.exit(), 3000); */
|
@ -0,0 +1,65 @@ |
|||
/* global it, describe, jasmine */ |
|||
global.net = require('net'); |
|||
let BlueElectrum = require('./BlueElectrum'); |
|||
let assert = require('assert'); |
|||
|
|||
describe('Electrum', () => { |
|||
it('ElectrumClient can connect and query', async () => { |
|||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; |
|||
const ElectrumClient = require('electrum-client'); |
|||
let bitcoin = require('bitcoinjs-lib'); |
|||
// let bitcoin = require('bitcoinjs-lib');
|
|||
|
|||
const peer = { host: 'electrum.coinucopia.io', ssl: 50002, tcp: 50001, pruning: null, http: null, https: null }; |
|||
console.log('begin connection:', JSON.stringify(peer)); |
|||
let mainClient = new ElectrumClient(peer.tcp, peer.host, 'tcp'); |
|||
|
|||
try { |
|||
await mainClient.connect(); |
|||
const ver = await mainClient.server_version('2.7.11', '1.2'); |
|||
console.log('connected to ', ver); |
|||
} catch (e) { |
|||
console.log('bad connection:', JSON.stringify(peer)); |
|||
throw new Error(); |
|||
} |
|||
|
|||
let addr4elect = 'bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej'; |
|||
let script = bitcoin.address.toOutputScript(addr4elect); |
|||
let hash = bitcoin.crypto.sha256(script); |
|||
let reversedHash = Buffer.from(hash.reverse()); |
|||
let balance = await mainClient.blockchainScripthash_getBalance(reversedHash.toString('hex')); |
|||
assert.ok(balance.confirmed > 0); |
|||
|
|||
addr4elect = '3GCvDBAktgQQtsbN6x5DYiQCMmgZ9Yk8BK'; |
|||
script = bitcoin.address.toOutputScript(addr4elect); |
|||
hash = bitcoin.crypto.sha256(script); |
|||
reversedHash = Buffer.from(hash.reverse()); |
|||
balance = await mainClient.blockchainScripthash_getBalance(reversedHash.toString('hex')); |
|||
assert.ok(balance.confirmed === 51432); |
|||
|
|||
// let peers = await mainClient.serverPeers_subscribe();
|
|||
// console.log(peers);
|
|||
mainClient.keepAlive = () => {}; // dirty hack to make it stop reconnecting
|
|||
mainClient.reconnect = () => {}; // dirty hack to make it stop reconnecting
|
|||
mainClient.close(); |
|||
// setTimeout(()=>process.exit(), 3000);
|
|||
}); |
|||
|
|||
it('BlueElectrum works', async function() { |
|||
let address = '3GCvDBAktgQQtsbN6x5DYiQCMmgZ9Yk8BK'; |
|||
await BlueElectrum.waitTillConnected(); |
|||
let balance = await BlueElectrum.getBalanceByAddress(address); |
|||
assert.strictEqual(balance.confirmed, 51432); |
|||
assert.strictEqual(balance.unconfirmed, 0); |
|||
assert.strictEqual(balance.addr, address); |
|||
|
|||
let txs = await BlueElectrum.getTransactionsByAddress(address); |
|||
assert.strictEqual(txs.length, 1); |
|||
for (let tx of txs) { |
|||
assert.ok(tx.tx_hash); |
|||
assert.ok(tx.height); |
|||
} |
|||
|
|||
BlueElectrum.forceDisconnect(); |
|||
}); |
|||
}); |
@ -0,0 +1,21 @@ |
|||
import { NavigationActions } from 'react-navigation'; |
|||
|
|||
let _navigator; |
|||
|
|||
function setTopLevelNavigator(navigatorRef) { |
|||
_navigator = navigatorRef; |
|||
} |
|||
|
|||
function navigate(routeName, params) { |
|||
_navigator.dispatch( |
|||
NavigationActions.navigate({ |
|||
routeName, |
|||
params, |
|||
}), |
|||
); |
|||
} |
|||
|
|||
export default { |
|||
navigate, |
|||
setTopLevelNavigator, |
|||
}; |
@ -0,0 +1,19 @@ |
|||
"""Helper definitions to glob .aar and .jar targets""" |
|||
|
|||
def create_aar_targets(aarfiles): |
|||
for aarfile in aarfiles: |
|||
name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] |
|||
lib_deps.append(":" + name) |
|||
android_prebuilt_aar( |
|||
name = name, |
|||
aar = aarfile, |
|||
) |
|||
|
|||
def create_jar_targets(jarfiles): |
|||
for jarfile in jarfiles: |
|||
name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] |
|||
lib_deps.append(":" + name) |
|||
prebuilt_jar( |
|||
name = name, |
|||
binary_jar = jarfile, |
|||
) |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,3 +1,3 @@ |
|||
<resources> |
|||
<string name="app_name">Blue Wallet</string> |
|||
<string name="app_name">BlueWallet</string> |
|||
</resources> |
|||
|
@ -1,93 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<com.android.support> |
|||
<support-compat versions="24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<leanback-v17 versions="21.0.0,21.0.2,21.0.3,22.0.0,22.1.0,22.1.1,22.2.0,22.2.1,23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<recommendation versions="23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-tv-provider versions="26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-vector-drawable versions="23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<recyclerview-v7 versions="21.0.0,21.0.2,21.0.3,22.0.0,22.1.0,22.1.1,22.2.0,22.2.1,23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<preference-leanback-v17 versions="23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<preference-v14 versions="23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<percent versions="22.2.0,23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-media-compat versions="24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<cardview-v7 versions="21.0.0,21.0.2,21.0.3,22.0.0,22.1.0,22.1.1,22.2.0,22.2.1,23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<wearable versions="26.0.0-alpha1"/> |
|||
<exifinterface versions="25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-annotations versions="19.1.0,20.0.0,21.0.0,21.0.2,21.0.3,22.0.0,22.1.0,22.1.1,22.2.0,22.2.1,23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<appcompat-v7 versions="18.0.0,19.0.0,19.0.1,19.1.0,20.0.0,21.0.0,21.0.2,21.0.3,22.0.0,22.1.0,22.1.1,22.2.0,22.2.1,23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<palette-v7 versions="21.0.0,21.0.2,21.0.3,22.0.0,22.1.0,22.1.1,22.2.0,22.2.1,23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<multidex-instrumentation versions="1.0.0,1.0.1,1.0.2,1.0.3"/> |
|||
<multidex versions="1.0.0,1.0.1,1.0.2,1.0.3"/> |
|||
<mediarouter-v7 versions="18.0.0,19.0.0,19.0.1,19.1.0,20.0.0,21.0.0,21.0.2,21.0.3,22.0.0,22.1.0,22.1.1,22.2.0,22.2.1,23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-alpha4,28.0.0-alpha5,28.0.0-beta01,28.0.0"/> |
|||
<preference-v7 versions="23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-dynamic-animation versions="25.3.0,25.3.1,25.4.0,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-fragment versions="24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<design versions="22.2.0,22.2.1,23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<transition versions="24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<customtabs versions="23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-core-ui versions="24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<gridlayout-v7 versions="13.0.0,18.0.0,19.0.0,19.0.1,19.1.0,20.0.0,21.0.0,21.0.2,21.0.3,22.0.0,22.1.0,22.1.1,22.2.0,22.2.1,23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<animated-vector-drawable versions="23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-core-utils versions="24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-v13 versions="13.0.0,18.0.0,19.0.0,19.0.1,19.1.0,20.0.0,21.0.0,21.0.2,21.0.3,22.0.0,22.1.0,22.1.1,22.2.0,22.2.1,23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<instantvideo versions="26.0.0-alpha1"/> |
|||
<support-v4 versions="13.0.0,18.0.0,19.0.0,19.0.1,19.1.0,20.0.0,21.0.0,21.0.2,21.0.3,22.0.0,22.1.0,22.1.1,22.2.0,22.2.1,23.0.0,23.0.1,23.1.0,23.1.1,23.2.0,23.2.1,23.3.0,23.4.0,24.0.0-alpha1,24.0.0-alpha2,24.0.0-beta1,24.0.0,24.1.0,24.1.1,24.2.0,24.2.1,25.0.0,25.0.1,25.1.0,25.1.1,25.2.0,25.3.0,25.3.1,25.4.0,26.0.0-alpha1,26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-emoji versions="26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<wear versions="26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-emoji-appcompat versions="26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-emoji-bundled versions="26.0.0-beta1,26.0.0-beta2,26.0.0,26.0.1,26.0.2,26.1.0,27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<support-content versions="27.0.0,27.0.1,27.0.2,27.1.0,27.1.1,28.0.0-alpha1"/> |
|||
<design-bottomnavigation versions="28.0.0-alpha1"/> |
|||
<design-button versions="28.0.0-alpha1"/> |
|||
<design-circularreveal-cardview versions="28.0.0-alpha1"/> |
|||
<design-bottomappbar versions="28.0.0-alpha1"/> |
|||
<design-card versions="28.0.0-alpha1"/> |
|||
<design-shape versions="28.0.0-alpha1"/> |
|||
<design-drawable versions="28.0.0-alpha1"/> |
|||
<design-bottomsheet versions="28.0.0-alpha1"/> |
|||
<design-floatingactionbutton versions="28.0.0-alpha1"/> |
|||
<design-circularreveal-coordinatorlayout versions="28.0.0-alpha1"/> |
|||
<design-textfield versions="28.0.0-alpha1"/> |
|||
<design-stateful versions="28.0.0-alpha1"/> |
|||
<design-circularreveal versions="28.0.0-alpha1"/> |
|||
<design-expandable versions="28.0.0-alpha1"/> |
|||
<design-navigation versions="28.0.0-alpha1"/> |
|||
<design-dialog versions="28.0.0-alpha1"/> |
|||
<design-canvas versions="28.0.0-alpha1"/> |
|||
<design-tabs versions="28.0.0-alpha1"/> |
|||
<design-chip versions="28.0.0-alpha1"/> |
|||
<design-snackbar versions="28.0.0-alpha1"/> |
|||
<design-theme versions="28.0.0-alpha1"/> |
|||
<design-math versions="28.0.0-alpha1"/> |
|||
<design-transformation versions="28.0.0-alpha1"/> |
|||
<design-widget versions="28.0.0-alpha1"/> |
|||
<design-animation versions="28.0.0-alpha1"/> |
|||
<design-typography versions="28.0.0-alpha1"/> |
|||
<design-color versions="28.0.0-alpha1"/> |
|||
<design-internal versions="28.0.0-alpha1"/> |
|||
<design-resources versions="28.0.0-alpha1"/> |
|||
<design-ripple versions="28.0.0-alpha1"/> |
|||
<coordinatorlayout versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<collections versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<slidingpanelayout versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<asynclayoutinflater versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<slices-view versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<recyclerview-selection versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<viewpager versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<cursoradapter versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<localbroadcastmanager versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<heifwriter versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<customview versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<print versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<slices-builders versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<interpolator versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<slices-core versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<loader versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<swiperefreshlayout versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<drawerlayout versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<documentfile versions="28.0.0-alpha1,28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<webkit versions="28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<car versions="28.0.0-alpha3,28.0.0-alpha4,28.0.0-alpha5"/> |
|||
<versionedparcelable versions="28.0.0-alpha3,28.0.0-beta01,28.0.0-rc01,28.0.0-rc02,28.0.0"/> |
|||
<media2 versions="28.0.0-alpha01,28.0.0-alpha02,28.0.0-alpha03"/> |
|||
</com.android.support> |
@ -1,120 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<metadata> |
|||
<com.android.support.constraint/> |
|||
<com.android.databinding/> |
|||
<com.android.support/> |
|||
<com.android.support.test/> |
|||
<com.android.support.test.janktesthelper/> |
|||
<com.android.support.test.uiautomator/> |
|||
<com.android.support.test.espresso/> |
|||
<android.arch.persistence.room/> |
|||
<android.arch.lifecycle/> |
|||
<android.arch.core/> |
|||
<com.google.android.instantapps/> |
|||
<com.google.android.instantapps.thirdpartycompat/> |
|||
<com.android.java.tools.build/> |
|||
<com.android.tools/> |
|||
<com.android.tools.layoutlib/> |
|||
<com.android.tools.ddms/> |
|||
<com.android.tools.external.com-intellij/> |
|||
<com.android.tools.build/> |
|||
<com.android.tools.analytics-library/> |
|||
<com.android.tools.internal.build.test/> |
|||
<com.android.tools.lint/> |
|||
<com.android.tools.external.org-jetbrains/> |
|||
<com.android.support.test.espresso.idling/> |
|||
<com.android.support.test.services/> |
|||
<com.google.firebase/> |
|||
<com.google.android.gms/> |
|||
<com.google.gms/> |
|||
<android.arch.paging/> |
|||
<com.crashlytics.sdk.android/> |
|||
<io.fabric.sdk.android/> |
|||
<android.arch.persistence/> |
|||
<com.google.android.wearable/> |
|||
<com.google.android.support/> |
|||
<com.android.installreferrer/> |
|||
<com.google.ar/> |
|||
<androidx.core/> |
|||
<com.google.android.things/> |
|||
<com.android.tools.build.jetifier/> |
|||
<tools.base.build-system.debug/> |
|||
<androidx.databinding/> |
|||
<androidx.constraintlayout/> |
|||
<org.chromium.net/> |
|||
<com.google.android.play/> |
|||
<androidx.multidex/> |
|||
<com.google.android.material/> |
|||
<androidx.test.services/> |
|||
<androidx.test.janktesthelper/> |
|||
<androidx.test/> |
|||
<androidx.test.espresso/> |
|||
<androidx.test.espresso.idling/> |
|||
<androidx.test.uiautomator/> |
|||
<androidx.room/> |
|||
<androidx.paging/> |
|||
<androidx.lifecycle/> |
|||
<androidx.sqlite/> |
|||
<androidx.arch.core/> |
|||
<android.arch.work/> |
|||
<android.arch.navigation/> |
|||
<androidx.mediarouter/> |
|||
<androidx.percentlayout/> |
|||
<androidx.emoji/> |
|||
<androidx.cardview/> |
|||
<androidx.preference/> |
|||
<androidx.wear/> |
|||
<androidx.legacy/> |
|||
<androidx.documentfile/> |
|||
<androidx.car/> |
|||
<androidx.swiperefreshlayout/> |
|||
<androidx.leanback/> |
|||
<androidx.appcompat/> |
|||
<androidx.customview/> |
|||
<androidx.gridlayout/> |
|||
<androidx.vectordrawable/> |
|||
<androidx.heifwriter/> |
|||
<androidx.transition/> |
|||
<androidx.print/> |
|||
<androidx.viewpager/> |
|||
<androidx.annotation/> |
|||
<androidx.exifinterface/> |
|||
<androidx.dynamicanimation/> |
|||
<androidx.browser/> |
|||
<androidx.localbroadcastmanager/> |
|||
<androidx.asynclayoutinflater/> |
|||
<androidx.contentpager/> |
|||
<androidx.slidingpanelayout/> |
|||
<androidx.cursoradapter/> |
|||
<androidx.media/> |
|||
<androidx.loader/> |
|||
<androidx.interpolator/> |
|||
<androidx.coordinatorlayout/> |
|||
<androidx.fragment/> |
|||
<androidx.tvprovider/> |
|||
<androidx.slice/> |
|||
<androidx.collection/> |
|||
<androidx.recommendation/> |
|||
<androidx.drawerlayout/> |
|||
<androidx.recyclerview/> |
|||
<androidx.webkit/> |
|||
<androidx.palette/> |
|||
<com.google.ar.sceneform/> |
|||
<com.google.ar.sceneform.ux/> |
|||
<androidx.test.ext/> |
|||
<com.google.android.ads.consent/> |
|||
<androidx.versionedparcelable/> |
|||
<androidx.media2/> |
|||
<com.google.ads.afsn/> |
|||
<com.google.android.ads/> |
|||
<androidx.biometric/> |
|||
<androidx.concurrent/> |
|||
<androidx.activity/> |
|||
<com.android.tools.apkparser/> |
|||
<com.android.tools.pixelprobe/> |
|||
<androidx.textclassifier/> |
|||
<androidx.remotecallback/> |
|||
<com.android.tools.chunkio/> |
|||
<com.android.tools.fakeadbserver/> |
|||
<androidx.savedstate/> |
|||
</metadata> |
@ -1,7 +1,4 @@ |
|||
{ |
|||
"displayName": "Blue Wallet", |
|||
"name": "BlueWallet", |
|||
"ios": { |
|||
"buildNumber": "118" |
|||
} |
|||
"displayName": "BlueWallet" |
|||
} |
@ -0,0 +1,3 @@ |
|||
module.exports = { |
|||
presets: ['module:metro-react-native-babel-preset'], |
|||
}; |
@ -0,0 +1,79 @@ |
|||
import { LegacyWallet } from './legacy-wallet'; |
|||
import { HDSegwitP2SHWallet } from './hd-segwit-p2sh-wallet'; |
|||
import { LightningCustodianWallet } from './lightning-custodian-wallet'; |
|||
import { HDLegacyBreadwalletWallet } from './hd-legacy-breadwallet-wallet'; |
|||
import { HDLegacyP2PKHWallet } from './hd-legacy-p2pkh-wallet'; |
|||
import { WatchOnlyWallet } from './watch-only-wallet'; |
|||
|
|||
export default class WalletGradient { |
|||
static defaultGradients = ['#65ceef', '#68bbe1']; |
|||
static watchOnlyWallet = ['#7d7d7d', '#4a4a4a']; |
|||
static legacyWallet = ['#40fad1', '#15be98']; |
|||
static hdLegacyP2PKHWallet = ['#e36dfa', '#bd10e0']; |
|||
static hdLegacyBreadWallet = ['#fe6381', '#f99c42']; |
|||
static hdSegwitP2SHWallet = ['#c65afb', '#9053fe']; |
|||
static lightningCustodianWallet = ['#f1be07', '#f79056']; |
|||
static createWallet = ['#eef0f4', '#eef0f4']; |
|||
|
|||
static gradientsFor(type) { |
|||
let gradient; |
|||
switch (type) { |
|||
case WatchOnlyWallet.type: |
|||
gradient = WalletGradient.watchOnlyWallet; |
|||
break; |
|||
case LegacyWallet.type: |
|||
gradient = WalletGradient.legacyWallet; |
|||
break; |
|||
case HDLegacyP2PKHWallet.type: |
|||
gradient = WalletGradient.hdLegacyP2PKHWallet; |
|||
break; |
|||
case HDLegacyBreadwalletWallet.type: |
|||
gradient = WalletGradient.hdLegacyBreadWallet; |
|||
break; |
|||
case HDSegwitP2SHWallet.type: |
|||
gradient = WalletGradient.hdSegwitP2SHWallet; |
|||
break; |
|||
case LightningCustodianWallet.type: |
|||
gradient = WalletGradient.lightningCustodianWallet; |
|||
break; |
|||
case 'CreateWallet': |
|||
gradient = WalletGradient.createWallet; |
|||
break; |
|||
default: |
|||
gradient = WalletGradient.defaultGradients; |
|||
break; |
|||
} |
|||
return gradient; |
|||
} |
|||
|
|||
static headerColorFor(type) { |
|||
let gradient; |
|||
switch (type) { |
|||
case WatchOnlyWallet.type: |
|||
gradient = WalletGradient.watchOnlyWallet; |
|||
break; |
|||
case LegacyWallet.type: |
|||
gradient = WalletGradient.legacyWallet; |
|||
break; |
|||
case HDLegacyP2PKHWallet.type: |
|||
gradient = WalletGradient.hdLegacyP2PKHWallet; |
|||
break; |
|||
case HDLegacyBreadwalletWallet.type: |
|||
gradient = WalletGradient.hdLegacyBreadWallet; |
|||
break; |
|||
case HDSegwitP2SHWallet.type: |
|||
gradient = WalletGradient.hdSegwitP2SHWallet; |
|||
break; |
|||
case LightningCustodianWallet.type: |
|||
gradient = WalletGradient.lightningCustodianWallet; |
|||
break; |
|||
case 'CreateWallet': |
|||
gradient = WalletGradient.createWallet; |
|||
break; |
|||
default: |
|||
gradient = WalletGradient.defaultGradients; |
|||
break; |
|||
} |
|||
return gradient[0]; |
|||
} |
|||
} |
File diff suppressed because it is too large
@ -1,41 +1,17 @@ |
|||
v.3.5.6 |
|||
------- |
|||
v3.7.2 |
|||
====== |
|||
|
|||
ADD: Loading indicator for wallet name change and wallet delete |
|||
ADD: Added CZK fiat |
|||
ADD: Alert user if they are trying to create a lightning wallet without a bitcoin wallet |
|||
ADD: French |
|||
ADD: DK - Danish Language Support |
|||
ADD: Thai locale |
|||
ADD: Dutch translation |
|||
FIX: Main wallet list shows transaction unit that is preferred by wallet |
|||
FIX: Export QRCode was too big on iPad |
|||
FIX: Don't override existing tx information when scanning invalid QR |
|||
FIX: Satoshis are now human-readable |
|||
FIX: crash when RBF |
|||
|
|||
v3.5.5 |
|||
------ |
|||
|
|||
ADD: pay zero-amount (tip) invoices |
|||
ADD: lightning withdrawal through zigzag |
|||
ADD: Thai translation |
|||
ADD: Dutch translation |
|||
ADD: Added Singapore Dollars |
|||
ADD: Added AUD, VEF, and ZAR fiats. |
|||
FIX: Loading indicator when creating a wallet |
|||
FIX: Changelly link |
|||
Fix and improve pt-BR translation |
|||
FIX: Cannot click on Lightning transactions #196 |
|||
FIX: Fixed a clipping issue in lightning settings |
|||
FIX: fixed a margin issue in about that caused clipping |
|||
FIX: Changed invoice description field to label |
|||
FIX: Updated transaction buttons maximum width |
|||
FIX: Main Buttons layout #204 |
|||
FIX: Add topup indication on wallet selection #207 |
|||
FIX: Invoice QR code wrong scale #203 |
|||
FIX: Don't allow user to pay for an invoice created with the same wallet. |
|||
FIX: If. balance was not a string, app would crash. |
|||
FIX: Changed language selection screen to FlatList |
|||
FIX: Made amount tap area larger |
|||
FIX: Fixed an issue in currency settings where the checkmark wouldn't be in the correct preference* Merge branch 'master' of github.com:BlueWallet/BlueWallet |
|||
* FIX: status bar disappears #311 |
|||
* FIX: faulty back button on viewLndInvoice screen |
|||
* FIX: lnd - create invoice - cant tap bottom half of button #303 |
|||
* FIX: Impossible to scan bech32 QR invoice with a specific amount (closes #296) |
|||
* REF: better lightning error reporting |
|||
* FIX: not redering QR code #302 |
|||
* ADD: Indonesian Translation |
|||
* FIX: better LN wallet auto-refresh strategy |
|||
* FIX: Dismiss keyboard when pressing return |
|||
* FIX: HD wallet balance refresh |
|||
* FIX: no wallet refresh upon startup (faster to start app) |
|||
* FIX: Dismiss keyboard when pressing return |
|||
* REF: HD wallet getbalance improvements |
|||
* ADD: NZD as a currency |
@ -0,0 +1,220 @@ |
|||
module.exports = { |
|||
_: { |
|||
storage_is_encrypted: 'Penyimpanan dienkripsi. Masukkan kata sandi untuk dekripsi:', |
|||
enter_password: 'Masukkan kata sandi', |
|||
bad_password: 'kata sandi salah, coba lagi', |
|||
never: 'tidak pernah', |
|||
continue: 'Lanjutkan', |
|||
ok: 'OK', |
|||
}, |
|||
wallets: { |
|||
select_wallet: 'Pilih dompet', |
|||
options: 'Opsi', |
|||
createBitcoinWallet: |
|||
'Belum ada dompet bitcoin. Untuk mendanai dompet Lightning, dompet Bitcoin harus dibuat atau diimpor. Yakin ingin melanjutkan?', |
|||
list: { |
|||
app_name: 'BlueWallet', |
|||
title: 'Dompet', |
|||
header: 'Sebuah dompet mewakili sepasang kunci rahasia dan sebuah alamat' + 'yang bisa dipilih untuk menerima koin.', |
|||
add: 'Tambah dompet', |
|||
create_a_wallet: 'Buat dompet', |
|||
create_a_wallet1: 'Gratis dan bisa buat', |
|||
create_a_wallet2: 'sebanyak yang kamu mau', |
|||
latest_transaction: 'transaksi terbaru', |
|||
empty_txs1: 'Transaksimu akan muncul di sini,', |
|||
empty_txs2: 'saat ini tidak ada transaksi', |
|||
tap_here_to_buy: 'Tap di sini untuk membeli bitcoin', |
|||
}, |
|||
reorder: { |
|||
title: 'Susun Dompet', |
|||
}, |
|||
add: { |
|||
title: 'tambah dompet', |
|||
description: |
|||
'Kamu bisa membuat dompet atau memindai paper wallet dalam WIF (Wallet Import Format). Bluewallet mendukung dompet Segwit.', |
|||
scan: 'Pindai', |
|||
create: 'Buat', |
|||
label_new_segwit: 'Dompet SegWit baru', |
|||
label_new_lightning: 'Dompet Lightning baru', |
|||
wallet_name: 'nama dompet', |
|||
wallet_type: 'tipe', |
|||
or: 'atau', |
|||
import_wallet: 'Impor dompet', |
|||
imported: 'Diimpor', |
|||
coming_soon: 'Akan datang', |
|||
lightning: 'Lightning', |
|||
bitcoin: 'Bitcoin', |
|||
}, |
|||
details: { |
|||
title: 'Dompet', |
|||
address: 'Alamat', |
|||
type: 'Tipe', |
|||
label: 'Label', |
|||
destination: 'tujuan', |
|||
description: 'deskripsi', |
|||
are_you_sure: 'Yakin?', |
|||
yes_delete: 'Ya, hapus', |
|||
no_cancel: 'Tidak, batalkan', |
|||
delete: 'Hapus', |
|||
save: 'Simpan', |
|||
delete_this_wallet: 'Hapus dompet ini', |
|||
export_backup: 'Ekspor / backup', |
|||
buy_bitcoin: 'Beli Bitcoin', |
|||
show_xpub: 'Tampilkan XPUB dompet', |
|||
}, |
|||
export: { |
|||
title: 'ekspor dompet', |
|||
}, |
|||
xpub: { |
|||
title: 'XPUB dompet', |
|||
copiedToClipboard: 'Disalin ke clipboard.', |
|||
}, |
|||
import: { |
|||
title: 'impor', |
|||
explanation: 'Ketik kata mnemonic, private key, WIF, atau apapun yang kamu punya. BlueWallet akan mencoba mengimpor dompet kamu.', |
|||
imported: 'Diimpor', |
|||
error: 'Gagal mengimpor. Pastikan data yang diketik benar.', |
|||
success: 'Berhasil', |
|||
do_import: 'Impor', |
|||
scan_qr: 'atau mau pindai QR code?', |
|||
}, |
|||
scanQrWif: { |
|||
go_back: 'Kembali', |
|||
cancel: 'Batal', |
|||
decoding: 'Membaca...', |
|||
input_password: 'Masukkan kata sandi', |
|||
password_explain: 'Ini adalah private key terenkripsi BIP38', |
|||
bad_password: 'kata sandi salah', |
|||
wallet_already_exists: 'Dompet sudah ada', |
|||
bad_wif: 'WIF salah', |
|||
imported_wif: 'WIF diimpor ', |
|||
with_address: ' dengan alamat ', |
|||
imported_segwit: 'Dompet SegWit diimpor', |
|||
imported_legacy: 'Dompet lawas diimpor', |
|||
imported_watchonly: 'Alamat tinjauan diimpor', |
|||
}, |
|||
}, |
|||
transactions: { |
|||
list: { |
|||
tabBarLabel: 'Transaksi', |
|||
title: 'transaksi', |
|||
description: 'Daftar transaksi keluar dan masuk dompet', |
|||
conf: 'konfirmasi', |
|||
}, |
|||
details: { |
|||
title: 'Transaksi', |
|||
from: 'Input', |
|||
to: 'Output', |
|||
copy: 'Salin', |
|||
transaction_details: 'Detail transaksi', |
|||
show_in_block_explorer: 'Tampilkan di block explorer', |
|||
}, |
|||
}, |
|||
send: { |
|||
header: 'Kirim', |
|||
details: { |
|||
title: 'buat transaksi', |
|||
amount_field_is_not_valid: 'Jumlah tidak valid', |
|||
fee_field_is_not_valid: 'Tarif tidak valid', |
|||
address_field_is_not_valid: 'Alamat tidak valid', |
|||
total_exceeds_balance: 'Jumlah yang dikirim melebihi saldo.', |
|||
create_tx_error: 'Kesalahan dalam membuat transaksi. Cek kembali alamat tujuan.', |
|||
address: 'alamat', |
|||
amount_placeholder: 'jumlah (dalam BTC)', |
|||
fee_placeholder: 'Tambahan biaya transaksi (dalam BTC)', |
|||
note_placeholder: 'catatan pribadi', |
|||
cancel: 'Batalkan', |
|||
scan: 'Pindai', |
|||
send: 'Kirim', |
|||
create: 'Buat', |
|||
remaining_balance: 'Sisa saldo', |
|||
}, |
|||
confirm: { |
|||
header: 'Konfirmasi', |
|||
sendNow: 'Kirim sekarang', |
|||
}, |
|||
success: { |
|||
done: 'Selesai', |
|||
}, |
|||
create: { |
|||
details: 'Detail', |
|||
title: 'buat transaksi', |
|||
error: 'Tidak bisa membuat transaksi. Cek alamat atau jumlah transfer.', |
|||
go_back: 'Kembali', |
|||
this_is_hex: 'Ini adalah hex transaksi, siap untuk disiarkan ke jaringan.', |
|||
to: 'Ke', |
|||
amount: 'Jumlah', |
|||
fee: 'Tarif', |
|||
tx_size: 'Ukuran TX', |
|||
satoshi_per_byte: 'Satoshi per byte', |
|||
memo: 'Memo', |
|||
broadcast: 'Siarkan', |
|||
not_enough_fee: 'Tarif tidak cukup. Naikkan tarif', |
|||
}, |
|||
}, |
|||
receive: { |
|||
header: 'Terima', |
|||
details: { |
|||
title: 'Bagikan alamat ini ke pengirim', |
|||
share: 'bagikan', |
|||
copiedToClipboard: 'Disalin ke clipboard.', |
|||
label: 'Deskripsi', |
|||
create: 'Buat', |
|||
setAmount: 'Terima sejumlah', |
|||
}, |
|||
}, |
|||
buyBitcoin: { |
|||
header: 'Beli bitcoin', |
|||
tap_your_address: 'Untuk menyalin, tap alamat:', |
|||
copied: 'Disalin ke Clipboard!', |
|||
}, |
|||
settings: { |
|||
header: 'setting', |
|||
plausible_deniability: 'Plausible deniability...', |
|||
storage_not_encrypted: 'Penyimpanan: tidak terenkripsi', |
|||
storage_encrypted: 'Penyimpanan: terenkripsi', |
|||
password: 'kata sandi', |
|||
password_explain: 'Buat kata sandi untuk dekripsi penyimpanan', |
|||
retype_password: 'Ulangi kata sandi', |
|||
passwords_do_not_match: 'Kata sandi tidak cocok', |
|||
encrypt_storage: 'Enkripsi penyimpanan', |
|||
lightning_settings: 'Pengaturan Lightning', |
|||
lightning_settings_explain: |
|||
'Pasang LndHub untuk menghubungkan ke node LND kamu' + |
|||
' dan masukkan URL di sini. Biarkan kosong untuk menghubungkan ke LndHub standar (lndhub.io)', |
|||
save: 'simpan', |
|||
about: 'Tentang', |
|||
language: 'Bahasa', |
|||
currency: 'Mata Uang', |
|||
}, |
|||
plausibledeniability: { |
|||
title: 'Plausible Deniability', |
|||
help: |
|||
'Under certain circumstances, you might be forced to disclose a ' + |
|||
'password. To keep your coins safe, BlueWallet can create another ' + |
|||
'encrypted storage, with a different password. Under pressure, ' + |
|||
'you can disclose this password to a 3rd party. If entered in ' + |
|||
"BlueWallet, it will unlock new 'fake' storage. This will seem " + |
|||
'legit to a 3rd party, but will secretly keep your main storage ' + |
|||
'with coins safe.', |
|||
help2: 'New storage will be fully functional, and you can store some ' + 'minimum amounts there so it looks more believable.', |
|||
create_fake_storage: 'Create fake encrypted storage', |
|||
go_back: 'Go Back', |
|||
create_password: 'Create a password', |
|||
create_password_explanation: 'Password for fake storage should not match password for your main storage', |
|||
password_should_not_match: 'Password for fake storage should not match password for your main storage', |
|||
retype_password: 'Retype password', |
|||
passwords_do_not_match: 'Passwords do not match, try again', |
|||
success: 'Success', |
|||
}, |
|||
lnd: { |
|||
title: 'atur dana', |
|||
choose_source_wallet: 'Pilih dompet sumber', |
|||
refill_lnd_balance: 'Isi ulang saldo Lightning', |
|||
refill: 'Isi ulang', |
|||
withdraw: 'Tarik', |
|||
placeholder: 'Invoice', |
|||
expired: 'Kadaluarsa', |
|||
sameWalletAsInvoiceError: 'Kamu tidak bisa membayar invoice dengan dompet yang sama yang dipakai untuk membuat invoice.', |
|||
}, |
|||
}; |
@ -0,0 +1,223 @@ |
|||
module.exports = { |
|||
_: { |
|||
storage_is_encrypted: 'ウォレットは暗号化されています。復号にはパスワードが必要です。', |
|||
enter_password: 'パスワードを入力', |
|||
bad_password: 'パスワードが間違っています。', |
|||
never: 'データなし', |
|||
continue: '続行', |
|||
ok: 'OK', |
|||
}, |
|||
wallets: { |
|||
select_wallet: 'ウォレット選択', |
|||
options: 'オプション', |
|||
createBitcoinWallet: |
|||
'Bitcoin ウォレットを持っていません。Lightning ウォレットへ課金する場合は Bitcoin ウォレットを新規作成するかインポートする必要があります。続行しますか?', |
|||
list: { |
|||
app_name: 'BlueWallet', |
|||
title: 'ウォレット', |
|||
header: 'ウォレットは秘密鍵(プライベートキー)とウォレットアドレスのペアで構成されています。' + 'コインを受信するために共有できます。', |
|||
add: 'ウォレットの追加', |
|||
create_a_wallet: 'ウォレットの作成', |
|||
create_a_wallet1: 'ウォレット作成は無料で', |
|||
create_a_wallet2: '好きなだけ複数作成できます', |
|||
latest_transaction: '最新の取引', |
|||
empty_txs1: 'ここに取引が表示されます', |
|||
empty_txs2: '現在は何もありません', |
|||
tap_here_to_buy: 'Bitcoin を購入するにはここをタップ', |
|||
}, |
|||
reorder: { |
|||
title: 'ウォレットの並び替え', |
|||
}, |
|||
add: { |
|||
title: 'ウォレットの追加', |
|||
description: |
|||
'ペーパーウォレット(WIF 形式- Wallet Import Format)をスキャンするかウォレットを新規作成できます。既定で Segwit ウォレットが作成されます。', |
|||
scan: '読取り', |
|||
create: '作成', |
|||
label_new_segwit: '新規 SegWit', |
|||
label_new_lightning: '新規 Lightning', |
|||
wallet_name: 'ウォレット名', |
|||
wallet_type: 'タイプ', |
|||
or: '又は', |
|||
import_wallet: 'ウォレットをインポート', |
|||
imported: 'インポート完了', |
|||
coming_soon: '準備中', |
|||
lightning: 'Lightning', |
|||
bitcoin: 'Bitcoin', |
|||
}, |
|||
details: { |
|||
title: 'ウォレット', |
|||
address: 'アドレス', |
|||
type: 'タイプ', |
|||
label: 'ラベル', |
|||
destination: '送り先', |
|||
description: '内容', |
|||
are_you_sure: '実行しますか?', |
|||
yes_delete: 'はい、削除します', |
|||
no_cancel: 'いいえ、中止します', |
|||
delete: '削除', |
|||
save: '保存', |
|||
delete_this_wallet: 'このウォレットの削除', |
|||
export_backup: 'エクスポート / バックアップ', |
|||
buy_bitcoin: 'Bitcoin の購入', |
|||
show_xpub: 'ウォレット XPUB の表示', |
|||
}, |
|||
export: { |
|||
title: 'ウォレットのエクスポート', |
|||
}, |
|||
xpub: { |
|||
title: 'ウォレット XPUB', |
|||
copiedToClipboard: 'クリップボードにコピーしました。', |
|||
}, |
|||
import: { |
|||
title: 'インポート', |
|||
explanation: |
|||
'ここにニモニック、秘密鍵(プライベートキー)、WIFなどを入力してください。BlueWallet が正しい形式を推測しウォレットをインポートします。', |
|||
imported: 'インポート完了', |
|||
error: 'インポートに失敗しました。入力したデータが有効か確認してください。', |
|||
success: '成功', |
|||
do_import: 'インポート', |
|||
scan_qr: 'QR コードの読み取り', |
|||
}, |
|||
scanQrWif: { |
|||
go_back: '戻る', |
|||
cancel: '中止', |
|||
decoding: '解読中', |
|||
input_password: 'パスワードの入力', |
|||
password_explain: 'これは BIP38 暗号化秘密鍵です', |
|||
bad_password: 'パスワードが違います', |
|||
wallet_already_exists: '同じウォレットが既に存在します', |
|||
bad_wif: 'WIF 形式が間違っています', |
|||
imported_wif: 'WIF インポート完了 ', |
|||
with_address: ' アドレス ', |
|||
imported_segwit: 'SegWit インポート完了', |
|||
imported_legacy: 'Legacy インポート完了', |
|||
imported_watchonly: '閲覧専用 インポート完了', |
|||
}, |
|||
}, |
|||
transactions: { |
|||
list: { |
|||
tabBarLabel: '取引', |
|||
title: '取引', |
|||
description: 'ウォレットの送金または入金のリスト', |
|||
conf: '確認', |
|||
}, |
|||
details: { |
|||
title: '取引', |
|||
from: '送り主', |
|||
to: '送り先', |
|||
copy: 'コピー', |
|||
transaction_details: '取引詳細', |
|||
show_in_block_explorer: 'Block Explorer で表示', |
|||
}, |
|||
}, |
|||
send: { |
|||
header: '送金', |
|||
details: { |
|||
title: '取引の作成', |
|||
amount_field_is_not_valid: '金額欄が正しくありません', |
|||
fee_field_is_not_valid: '手数料欄が正しくありません', |
|||
address_field_is_not_valid: 'アドレス欄が正しくありません', |
|||
total_exceeds_balance: '送金額が利用可能残額を超えています。', |
|||
create_tx_error: '取引作成中にエラーが発生しました。有効な送金アドレスか確認してください。', |
|||
address: 'アドレス', |
|||
amount_placeholder: '送金額 (BTC)', |
|||
fee_placeholder: '取引手数料 (BTC)', |
|||
note_placeholder: 'ラベル', |
|||
cancel: '中止', |
|||
scan: '読取り', |
|||
send: '送金', |
|||
create: '作成', |
|||
remaining_balance: '残高', |
|||
}, |
|||
confirm: { |
|||
header: '確認', |
|||
sendNow: '送金実行', |
|||
}, |
|||
success: { |
|||
done: '完了', |
|||
}, |
|||
create: { |
|||
details: '詳細', |
|||
title: '取引の作成', |
|||
error: '取引作成でエラーが発生しました。アドレスまたは送金額を確認してください。', |
|||
go_back: '戻る', |
|||
this_is_hex: '署名されネットワークへ送信される 16 進数取引コードです', |
|||
to: '送金先', |
|||
amount: '送金額', |
|||
fee: '手数料', |
|||
tx_size: 'TX サイズ', |
|||
satoshi_per_byte: 'Satoshi/byte', |
|||
memo: 'メモ', |
|||
broadcast: '送信', |
|||
not_enough_fee: '手数料不足です。増額してください', |
|||
}, |
|||
}, |
|||
receive: { |
|||
header: '入金', |
|||
details: { |
|||
title: 'このアドレスを支払者と共有', |
|||
share: '共有', |
|||
copiedToClipboard: 'クリップボードにコピーしました。', |
|||
label: '概要', |
|||
create: '作成', |
|||
setAmount: '入金額', |
|||
}, |
|||
}, |
|||
buyBitcoin: { |
|||
header: 'Bitcoin の購入', |
|||
tap_your_address: 'タップしてアドレスをクリップボードにコピー:', |
|||
copied: 'クリップボードにコピーしました!', |
|||
}, |
|||
settings: { |
|||
header: '設定', |
|||
plausible_deniability: '隠匿設定...', |
|||
storage_not_encrypted: 'ウォレット: 暗号化されていません', |
|||
storage_encrypted: 'ウォレット: 暗号化されています', |
|||
password: 'パスワード', |
|||
password_explain: 'ウォレットの復号に使用するパスワードを作成', |
|||
retype_password: 'パスワードの再入力', |
|||
passwords_do_not_match: 'パスワードが一致しません', |
|||
encrypt_storage: 'ウォレットの暗号化', |
|||
lightning_settings: 'Lightning 設定', |
|||
lightning_settings_explain: |
|||
'他の LND ノードへ接続するには LndHub をインストール後、' + |
|||
'URL を入力してください。既定の設定を使用するには空欄にします' + |
|||
'ndHub\n (lndhub.io)', |
|||
save: '保存', |
|||
about: 'BlueWallet について', |
|||
language: '言語', |
|||
currency: '通貨', |
|||
}, |
|||
plausibledeniability: { |
|||
title: '隠匿設定', |
|||
help: |
|||
'BuleWallet のウォレットの復号に必要なパスワードを第三者に強要される場合、' + |
|||
'コインを安全に保護するためにメインのウォレットとは異なるパスワードで' + |
|||
'暗号化されたダミーのウォレットを作成することが可能です。' + |
|||
'第三者へ異なるパスワードを提供すれば、BlueWallet のダミーの' + |
|||
'暗号化ウォレットを復号することとなり、メインのウォレットは隠匿され' + |
|||
'コインは安全に保護されます。', |
|||
help2: |
|||
'新規のダミーのウォレットはメインと同様に機能します。少額のコインを入金しておくことで' + |
|||
'ダミーと疑われないようにすることが可能です。', |
|||
create_fake_storage: 'ダミーの暗号化ウォレットの作成', |
|||
go_back: '戻る', |
|||
create_password: 'パスワードの作成', |
|||
create_password_explanation: 'ダミーのウォレットのパスワードはメインのウォレットのパスワードと異なる必要があります。', |
|||
password_should_not_match: 'ダミーのウォレットのパスワードはメインのウォレットのパスワードと異なる必要があります。', |
|||
retype_password: 'パスワードの再入力', |
|||
passwords_do_not_match: 'パスワードが一致しません', |
|||
success: '成功', |
|||
}, |
|||
lnd: { |
|||
title: '資金の管理', |
|||
choose_source_wallet: '送金元ウォレットを選択', |
|||
refill_lnd_balance: 'Lightning ウォレットへ送金', |
|||
refill: '送金', |
|||
withdraw: '引き出し', |
|||
placeholder: '入金依頼', |
|||
expired: '失効', |
|||
sameWalletAsInvoiceError: '以前作成したウォレットと同じウォレットへの支払いはできません。', |
|||
}, |
|||
}; |
@ -0,0 +1,215 @@ |
|||
module.exports = { |
|||
_: { |
|||
storage_is_encrypted: '你的信息已经被加密, 请输入密码解密', |
|||
enter_password: '输入密码', |
|||
bad_password: '密码无效,请重试', |
|||
never: '不', |
|||
continue: '继续', |
|||
ok: '好的', |
|||
}, |
|||
wallets: { |
|||
select_wallet: '选择钱包', |
|||
options: '选项', |
|||
createBitcoinWallet: '您当前没有bitcoin钱包. 为了支持闪电钱包, 我们需要创建或者导入一个比特币钱包. 是否需要继续?', |
|||
list: { |
|||
app_name: 'BlueWallet', |
|||
title: '钱包', |
|||
header: '一个钱包代表一对的私钥和地址' + '你可以通过分享收款.', |
|||
add: '添加钱包', |
|||
create_a_wallet: '创建一个钱包', |
|||
create_a_wallet1: '创建钱包是免费的,你可以', |
|||
create_a_wallet2: '想创建多少就创建多少个', |
|||
latest_transaction: '最近的转账', |
|||
empty_txs1: '你的转账信息将展示在这里', |
|||
empty_txs2: '当前无信息', |
|||
tap_here_to_buy: '点击购买比特币', |
|||
}, |
|||
reorder: { |
|||
title: '重新排列钱包', |
|||
}, |
|||
add: { |
|||
title: '添加钱包', |
|||
description: '你可以扫描你的纸质备份钱包 (WIF格式), 或者创建一个新钱包. 默认支持隔离见证钱包', |
|||
scan: '扫描', |
|||
create: '创建', |
|||
label_new_segwit: '新隔离见证(Segwit)', |
|||
label_new_lightning: '新闪电', |
|||
wallet_name: '钱包名称', |
|||
wallet_type: '类型', |
|||
or: '或', |
|||
import_wallet: '导入钱包', |
|||
imported: '已经导入', |
|||
coming_soon: '即将来临', |
|||
lightning: '闪电', |
|||
bitcoin: '比特币', |
|||
}, |
|||
details: { |
|||
title: '钱包', |
|||
address: '地址', |
|||
type: '类型', |
|||
label: '标签', |
|||
destination: '目的', |
|||
description: '描述', |
|||
are_you_sure: '你确认么?', |
|||
yes_delete: '是的,删除', |
|||
no_cancel: '不,取消', |
|||
delete: '删除', |
|||
save: '保存', |
|||
delete_this_wallet: '删除这个钱包', |
|||
export_backup: '导出备份', |
|||
buy_bitcoin: '购买比特币', |
|||
show_xpub: '展示钱包 XPUB', |
|||
}, |
|||
export: { |
|||
title: '钱包导出', |
|||
}, |
|||
xpub: { |
|||
title: '钱包 XPUB', |
|||
copiedToClipboard: '复制到粘贴板.', |
|||
}, |
|||
import: { |
|||
title: '导入', |
|||
explanation: '输入你的助记词,私钥或者WIF, 或者其他格式的数据. BlueWallet将尽可能的自动识别数据格式并导入钱包', |
|||
imported: '已经导入', |
|||
error: '导入失败,请确认你提供的信息是有效的', |
|||
success: '成功', |
|||
do_import: '导入', |
|||
scan_qr: '或扫面二维码', |
|||
}, |
|||
scanQrWif: { |
|||
go_back: '回退', |
|||
cancel: '取消', |
|||
decoding: '解码中', |
|||
input_password: '输入密码', |
|||
password_explain: '这是一个BIP38加密的私钥', |
|||
bad_password: '密码错误', |
|||
wallet_already_exists: '当前钱包已经存在', |
|||
bad_wif: 'WIF格式无效', |
|||
imported_wif: 'WIF已经导入', |
|||
with_address: ' 地址为', |
|||
imported_segwit: 'SegWit已经导入', |
|||
imported_legacy: 'Legacy已经导入', |
|||
imported_watchonly: '导入只读', |
|||
}, |
|||
}, |
|||
transactions: { |
|||
list: { |
|||
tabBarLabel: '转账', |
|||
title: '转账', |
|||
description: '当前所有钱包的转入和转出记录', |
|||
conf: '配置', |
|||
}, |
|||
details: { |
|||
title: '转账', |
|||
from: '输入', |
|||
to: '输出', |
|||
copy: '复制', |
|||
transaction_details: '转账详情', |
|||
show_in_block_explorer: '区块浏览器展示', |
|||
}, |
|||
}, |
|||
send: { |
|||
header: '发送', |
|||
details: { |
|||
title: '创建交易', |
|||
amount_field_is_not_valid: '金额格式无效', |
|||
fee_field_is_not_valid: '费用格式无效', |
|||
address_field_is_not_valid: '地址内容无效', |
|||
total_exceeds_balance: '余额不足', |
|||
create_tx_error: '创建交易失败. 请确认地址格式正确.', |
|||
address: '地址', |
|||
amount_placeholder: '发送金额(in BTC)', |
|||
fee_placeholder: '手续费用 (in BTC)', |
|||
note_placeholder: '消息', |
|||
cancel: '取消', |
|||
scan: '扫描', |
|||
send: '发送', |
|||
create: '创建', |
|||
remaining_balance: '剩余金额', |
|||
}, |
|||
confirm: { |
|||
header: '确认', |
|||
sendNow: '现在发送', |
|||
}, |
|||
success: { |
|||
done: '完成', |
|||
}, |
|||
create: { |
|||
details: '详情', |
|||
title: '创建详情', |
|||
error: '创建交易失败. 无效地址或金额?', |
|||
go_back: '回退', |
|||
this_is_hex: '这个是交易的十六进制数据, 签名并广播到全网络.', |
|||
to: '到', |
|||
amount: '金额', |
|||
fee: '手续费', |
|||
tx_size: '交易大小', |
|||
satoshi_per_byte: '葱每byte', |
|||
memo: '消息', |
|||
broadcast: '广播', |
|||
not_enough_fee: '手续费不够,请增加手续费', |
|||
}, |
|||
}, |
|||
receive: { |
|||
header: '收款', |
|||
details: { |
|||
title: '分享这个地址给付款人', |
|||
share: '分享', |
|||
copiedToClipboard: '复制到粘贴板.', |
|||
label: '描述', |
|||
create: '创建', |
|||
setAmount: '收款金额', |
|||
}, |
|||
}, |
|||
buyBitcoin: { |
|||
header: '购买比特币', |
|||
tap_your_address: '点击地址复制到粘贴板:', |
|||
copied: '复制到粘贴板!', |
|||
}, |
|||
settings: { |
|||
header: '设置', |
|||
plausible_deniability: '可否认性...', |
|||
storage_not_encrypted: '存储:未加密', |
|||
storage_encrypted: '存储:加密中', |
|||
password: '密码', |
|||
password_explain: '创建你的加密密码', |
|||
retype_password: '再次输入密码', |
|||
passwords_do_not_match: '两次输入密码不同', |
|||
encrypt_storage: '加密存储', |
|||
lightning_settings: '闪电网络设置', |
|||
lightning_settings_explain: '如要要连接你自己的闪电节点请安装LndHub' + ' 并把url地址输入到下面. 空白将使用默认的LndHub (lndhub.io)', |
|||
save: '保存', |
|||
about: '关于', |
|||
language: '语言', |
|||
currency: '货币', |
|||
}, |
|||
plausibledeniability: { |
|||
title: '可否认性', |
|||
help: |
|||
'在某些情况下, 你不得不暴露 ' + |
|||
'密码. 为了让你的比特币更加安全, BlueWallet可以创建一些 ' + |
|||
'加密空间, 用不同的密码. 在压力之下, ' + |
|||
'你可以暴露这个钱包密码. 再次进入 ' + |
|||
'BlueWallet, 我们会解锁一些虚拟空间. 对第三方来说看上去' + |
|||
'是合理的, 但会偷偷的帮你保证主钱包的安全 ' + |
|||
'币也就安全了.', |
|||
help2: '新的空间具备完整的功能,你可以存在 ' + '少量的金额在里面.', |
|||
create_fake_storage: '创建虚拟加密存储', |
|||
go_back: '回退', |
|||
create_password: '创建密码', |
|||
create_password_explanation: '虚拟存储空间密码不能和主存储空间密码相同', |
|||
password_should_not_match: '虚拟存储空间密码不能和主存储空间密码相同', |
|||
retype_password: '重输密码', |
|||
passwords_do_not_match: '两次输入密码不同,请重新输入', |
|||
success: '成功', |
|||
}, |
|||
lnd: { |
|||
title: '配置资金支持', |
|||
choose_source_wallet: '选择一个资金源钱包', |
|||
refill_lnd_balance: '给闪电钱包充值', |
|||
refill: '充值', |
|||
withdraw: '提取', |
|||
expired: '超时', |
|||
sameWalletAsInvoiceError: '你不能用创建账单的钱包去支付该账单', |
|||
}, |
|||
}; |
File diff suppressed because it is too large
@ -1,15 +1,15 @@ |
|||
diff --git a/node_modules/metro-minify-uglify/src/minifier.js b/node_modules/metro-minify-uglify/src/minifier.js
|
|||
index 021df4c..dcea186 100644
|
|||
index b703ee4..fadc077 100644
|
|||
--- a/node_modules/metro-minify-uglify/src/minifier.js
|
|||
+++ b/node_modules/metro-minify-uglify/src/minifier.js
|
|||
@@ -44,9 +44,7 @@ function minify(_ref) {
|
|||
reserved = _ref.reserved, |
|||
@@ -67,9 +67,7 @@ function minify(_ref) {
|
|||
config = _ref.config; |
|||
const options = _extends({}, config, { |
|||
- mangle: _extends({}, config.mangle, {
|
|||
|
|||
const options = _objectSpread({}, config, { |
|||
- mangle: _objectSpread({}, config.mangle, {
|
|||
- reserved
|
|||
- }),
|
|||
+ mangle: false, // !!!!!!!!!!!!!!!!
|
|||
|
|||
sourceMap: _extends({}, config.sourceMap, { |
|||
+ mangle: false, // !!!!!!!!!!!!!!!!!!!!!!!!
|
|||
sourceMap: _objectSpread({}, config.sourceMap, { |
|||
content: map |
|||
}) |
|||
|
@ -0,0 +1,501 @@ |
|||
import React, { Component } from 'react'; |
|||
import { TouchableOpacity, ActivityIndicator, View, Platform, Alert, Dimensions } from 'react-native'; |
|||
import { WebView } from 'react-native-webview'; |
|||
import WKWebView from 'react-native-wkwebview-reborn'; |
|||
import { BlueNavigationStyle, SafeBlueArea } from '../../BlueComponents'; |
|||
import { FormInput } from 'react-native-elements'; |
|||
import Ionicons from 'react-native-vector-icons/Ionicons'; |
|||
import PropTypes from 'prop-types'; |
|||
const { width } = Dimensions.get('window'); |
|||
|
|||
let processedInvoices = {}; |
|||
let lastTimeTriedToPay = 0; |
|||
|
|||
/// ///////////////////////////////////////////////////////////////////////
|
|||
// this code has no use in RN, it gets copypasted in webview injected code
|
|||
//
|
|||
let bluewalletResponses = {}; |
|||
// eslint-disable-next-line
|
|||
var webln = { |
|||
enable: function() { |
|||
window.postMessage(JSON.stringify({ enable: true })); |
|||
return new Promise(function(resolve, reject) { |
|||
resolve(true); |
|||
}); |
|||
}, |
|||
getInfo: function() { |
|||
window.postMessage('getInfo'); |
|||
return new Promise(function(resolve, reject) { |
|||
reject(new Error('not implemented')); |
|||
}); |
|||
}, |
|||
sendPayment: function(paymentRequest) { |
|||
window.postMessage(JSON.stringify({ sendPayment: paymentRequest })); |
|||
return new Promise(function(resolve, reject) { |
|||
/* nop. intentionally, forever hang promise. |
|||
lapp page usually asynchroniously checks payment itself, via ajax, |
|||
so atm there's no need to pass payment preimage from RN to webview and fullfill promise. |
|||
might change in future */ |
|||
}); |
|||
}, |
|||
makeInvoice: function(RequestInvoiceArgs) { |
|||
var id = Math.random(); |
|||
window.postMessage(JSON.stringify({ makeInvoice: RequestInvoiceArgs, id: id })); |
|||
return new Promise(function(resolve, reject) { |
|||
var interval = setInterval(function() { |
|||
if (bluewalletResponses[id]) { |
|||
clearInterval(interval); |
|||
resolve(bluewalletResponses[id]); |
|||
} |
|||
}, 1000); |
|||
}); |
|||
}, |
|||
signMessage: function() { |
|||
window.postMessage('signMessage'); |
|||
return new Promise(function(resolve, reject) { |
|||
reject(new Error('not implemented')); |
|||
}); |
|||
}, |
|||
verifyMessage: function() { |
|||
window.postMessage('verifyMessage'); |
|||
return new Promise(function(resolve, reject) { |
|||
reject(new Error('not implemented')); |
|||
}); |
|||
}, |
|||
}; |
|||
// end injected code
|
|||
/// /////////////////
|
|||
/// /////////////////
|
|||
|
|||
let alreadyInjected = false; |
|||
const injectedParadise = ` |
|||
|
|||
/* rules: |
|||
no 'let', only 'var' |
|||
no arrow functions |
|||
globals without 'var' |
|||
should work if compressed to single line |
|||
*/ |
|||
|
|||
|
|||
|
|||
/* this is a storage of responses from OUTER code (react native) |
|||
it gets written by message bus handler callback: |
|||
webview makes a call through bus to RN, each request with a unique ID. |
|||
RN processes the request from the bus, and posts response to the bus, with the same ID. |
|||
webview callback handler writes it in this hashmap. Then, some other code that patiently |
|||
waits for a response will see that the answer with such ID is present, and will fulfill a promise */ |
|||
|
|||
bluewalletResponses = {}; |
|||
|
|||
|
|||
/* this is injected WEBLN provider */ |
|||
|
|||
|
|||
webln = { |
|||
enable : function () { |
|||
window.postMessage(JSON.stringify({'enable': true})); |
|||
return new Promise(function(resolve, reject){ |
|||
resolve(true); |
|||
}) |
|||
}, |
|||
getInfo : function () { |
|||
window.postMessage('getInfo'); |
|||
return new Promise(function(resolve, reject){ |
|||
reject('not implemented'); |
|||
}) |
|||
}, |
|||
sendPayment: function(paymentRequest) { |
|||
window.postMessage(JSON.stringify({ sendPayment: paymentRequest })); |
|||
return new Promise(function(resolve, reject) { |
|||
/* nop. intentionally, forever hang promise. |
|||
lapp page usually asynchroniously checks payment itself, via ajax, |
|||
so atm there's no need to pass payment preimage from RN to webview and fullfill promise. |
|||
might change in future */ |
|||
}); |
|||
}, |
|||
makeInvoice: function (RequestInvoiceArgs) { |
|||
var id = Math.random(); |
|||
window.postMessage(JSON.stringify({makeInvoice: RequestInvoiceArgs, id: id})); |
|||
return new Promise(function(resolve, reject) { |
|||
var interval = setInterval(function () { |
|||
if (bluewalletResponses[id]) { |
|||
clearInterval(interval); |
|||
resolve(bluewalletResponses[id]); |
|||
} |
|||
}, 1000); |
|||
}); |
|||
}, |
|||
signMessage: function () { |
|||
window.postMessage('signMessage'); |
|||
return new Promise(function(resolve, reject){ |
|||
reject('not implemented'); |
|||
}) |
|||
}, |
|||
verifyMessage: function () { |
|||
window.postMessage('verifyMessage'); |
|||
return new Promise(function(resolve, reject){ |
|||
reject('not implemented'); |
|||
}) |
|||
}, |
|||
}; |
|||
|
|||
|
|||
/* end WEBLN */ |
|||
|
|||
/* listening to events that might come from RN: */ |
|||
document.addEventListener("message", function(event) { |
|||
window.postMessage("inside webview, received post message: " + event.data); |
|||
var json; |
|||
try { |
|||
json = JSON.parse(event.data); |
|||
} catch (_) {} |
|||
|
|||
if (json && json.bluewalletResponse) { |
|||
/* this is an answer to one of our inside-webview calls. |
|||
we store it in answers hashmap for someone who cares about it */ |
|||
bluewalletResponses[json.id] = json.bluewalletResponse |
|||
} |
|||
|
|||
}, false); |
|||
|
|||
|
|||
|
|||
|
|||
function tryToPay(invoice) { |
|||
window.postMessage(JSON.stringify({sendPayment:invoice})); |
|||
} |
|||
|
|||
/* for non-webln compatible pages we do it oldschool, |
|||
searching for all bolt11 manually */ |
|||
|
|||
setInterval(function() { |
|||
window.postMessage('interval'); |
|||
|
|||
var searchText = "lnbc"; |
|||
|
|||
var aTags = document.getElementsByTagName("span"); |
|||
var i; |
|||
for (i = 0; i < aTags.length; i++) { |
|||
if (aTags[i].textContent.indexOf(searchText) === 0) { |
|||
tryToPay(aTags[i].textContent); |
|||
} |
|||
} |
|||
|
|||
/* ------------------------- */ |
|||
|
|||
aTags = document.getElementsByTagName("input"); |
|||
for (i = 0; i < aTags.length; i++) { |
|||
if (aTags[i].value.indexOf(searchText) === 0) { |
|||
tryToPay(aTags[i].value); |
|||
} |
|||
} |
|||
|
|||
/* ------------------------- */ |
|||
|
|||
aTags = document.getElementsByTagName("a"); |
|||
searchText = "lightning:lnbc"; |
|||
|
|||
|
|||
for (i = 0; i < aTags.length; i++) { |
|||
var href = aTags[i].getAttribute('href') + ''; |
|||
if (href.indexOf(searchText) === 0) { |
|||
tryToPay(href.replace('lightning:', '')); |
|||
} |
|||
} |
|||
|
|||
}, 1000); |
|||
|
|||
`;
|
|||
|
|||
export default class Browser extends Component { |
|||
static navigationOptions = ({ navigation }) => ({ |
|||
...BlueNavigationStyle(navigation, true), |
|||
title: 'Lapp Browser', |
|||
headerLeft: null, |
|||
}); |
|||
|
|||
constructor(props) { |
|||
super(props); |
|||
if (!props.navigation.getParam('fromSecret')) throw new Error('Invalid param'); |
|||
if (!props.navigation.getParam('fromWallet')) throw new Error('Invalid param'); |
|||
|
|||
this.state = { |
|||
url: 'https://bluewallet.io/marketplace/', |
|||
pageIsLoading: false, |
|||
fromSecret: props.navigation.getParam('fromSecret'), |
|||
fromWallet: props.navigation.getParam('fromWallet'), |
|||
}; |
|||
} |
|||
|
|||
renderWebView = () => { |
|||
if (Platform.OS === 'android') { |
|||
return ( |
|||
<WebView |
|||
ref={ref => (this.webview = ref)} |
|||
source={{ uri: this.state.url }} |
|||
onMessage={e => { |
|||
// this is a handler which receives messages sent from within the browser
|
|||
console.log('---- message from the bus:', e.nativeEvent.data); |
|||
let json = false; |
|||
try { |
|||
json = JSON.parse(e.nativeEvent.data); |
|||
} catch (_) {} |
|||
// message from browser has ln invoice
|
|||
if (json && json.sendPayment) { |
|||
// checking that already asked about this invoice:
|
|||
if (processedInvoices[json.sendPayment]) { |
|||
return; |
|||
} else { |
|||
// checking that we do not trigger alert too often:
|
|||
if (+new Date() - lastTimeTriedToPay < 3000) { |
|||
return; |
|||
} |
|||
lastTimeTriedToPay = +new Date(); |
|||
//
|
|||
processedInvoices[json.sendPayment] = 1; |
|||
} |
|||
|
|||
Alert.alert( |
|||
'Page', |
|||
'This page asks for permission to pay an invoice', |
|||
[ |
|||
{ text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel' }, |
|||
{ |
|||
text: 'Pay', |
|||
onPress: () => { |
|||
console.log('OK Pressed'); |
|||
this.props.navigation.navigate({ |
|||
routeName: 'ScanLndInvoice', |
|||
params: { |
|||
uri: json.sendPayment, |
|||
fromSecret: this.state.fromSecret, |
|||
}, |
|||
}); |
|||
}, |
|||
}, |
|||
], |
|||
{ cancelable: false }, |
|||
); |
|||
} |
|||
|
|||
if (json && json.makeInvoice) { |
|||
let amount = Math.max(+json.makeInvoice.minimumAmount, +json.makeInvoice.maximumAmount, +json.makeInvoice.defaultAmount); |
|||
Alert.alert( |
|||
'Page', |
|||
'This page wants to pay you ' + amount + ' sats (' + json.makeInvoice.defaultMemo + ')', |
|||
[ |
|||
{ text: 'No thanks', onPress: () => console.log('Cancel Pressed'), style: 'cancel' }, |
|||
{ |
|||
text: 'Accept', |
|||
onPress: async () => { |
|||
/** @type {LightningCustodianWallet} */ |
|||
const fromWallet = this.state.fromWallet; |
|||
const payreq = await fromWallet.addInvoice(amount, json.makeInvoice.defaultMemo || ' '); |
|||
this.webview.postMessage(JSON.stringify({ bluewalletResponse: { paymentRequest: payreq }, id: json.id })); |
|||
}, |
|||
}, |
|||
], |
|||
{ cancelable: false }, |
|||
); |
|||
} |
|||
|
|||
if (json && json.enable) { |
|||
console.log('webln enabled'); |
|||
this.setState({ weblnEnabled: true }); |
|||
} |
|||
}} |
|||
onLoadStart={e => { |
|||
alreadyInjected = false; |
|||
console.log('load start'); |
|||
this.setState({ pageIsLoading: true, weblnEnabled: false }); |
|||
}} |
|||
onLoadEnd={e => { |
|||
console.log('load end'); |
|||
this.setState({ url: e.nativeEvent.url, pageIsLoading: false }); |
|||
}} |
|||
onLoadProgress={e => { |
|||
console.log('progress:', e.nativeEvent.progress); |
|||
if (!alreadyInjected && e.nativeEvent.progress > 0.5) { |
|||
this.webview.injectJavaScript(injectedParadise); |
|||
alreadyInjected = true; |
|||
console.log('injected'); |
|||
} |
|||
}} |
|||
/> |
|||
); |
|||
} else if (Platform.OS === 'ios') { |
|||
return ( |
|||
<WKWebView |
|||
ref={ref => (this.webview = ref)} |
|||
source={{ uri: this.state.url }} |
|||
injectJavaScript={injectedParadise} |
|||
onMessage={e => { |
|||
// this is a handler which receives messages sent from within the browser
|
|||
console.log('---- message from the bus:', e.nativeEvent.data); |
|||
let json = false; |
|||
try { |
|||
json = JSON.parse(e.nativeEvent.data); |
|||
} catch (_) {} |
|||
// message from browser has ln invoice
|
|||
if (json && json.sendPayment) { |
|||
// checking that we do not trigger alert too often:
|
|||
if (+new Date() - lastTimeTriedToPay < 3000) { |
|||
return; |
|||
} |
|||
lastTimeTriedToPay = +new Date(); |
|||
|
|||
// checking that already asked about this invoice:
|
|||
if (processedInvoices[json.sendPayment]) { |
|||
return; |
|||
} else { |
|||
processedInvoices[json.sendPayment] = 1; |
|||
} |
|||
|
|||
Alert.alert( |
|||
'Page', |
|||
'This page asks for permission to pay an invoice', |
|||
[ |
|||
{ text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel' }, |
|||
{ |
|||
text: 'Pay', |
|||
onPress: () => { |
|||
console.log('OK Pressed'); |
|||
this.props.navigation.navigate({ |
|||
routeName: 'ScanLndInvoice', |
|||
params: { |
|||
uri: json.sendPayment, |
|||
fromSecret: this.state.fromSecret, |
|||
}, |
|||
}); |
|||
}, |
|||
}, |
|||
], |
|||
{ cancelable: false }, |
|||
); |
|||
} |
|||
|
|||
if (json && json.makeInvoice) { |
|||
let amount = Math.max(+json.makeInvoice.minimumAmount, +json.makeInvoice.maximumAmount, +json.makeInvoice.defaultAmount); |
|||
Alert.alert( |
|||
'Page', |
|||
'This page wants to pay you ' + amount + ' sats (' + json.makeInvoice.defaultMemo + ')', |
|||
[ |
|||
{ text: 'No thanks', onPress: () => console.log('Cancel Pressed'), style: 'cancel' }, |
|||
{ |
|||
text: 'Accept', |
|||
onPress: async () => { |
|||
/** @type {LightningCustodianWallet} */ |
|||
const fromWallet = this.state.fromWallet; |
|||
const payreq = await fromWallet.addInvoice(amount, json.makeInvoice.defaultMemo || ' '); |
|||
this.webview.postMessage(JSON.stringify({ bluewalletResponse: { paymentRequest: payreq }, id: json.id })); |
|||
}, |
|||
}, |
|||
], |
|||
{ cancelable: false }, |
|||
); |
|||
} |
|||
|
|||
if (json && json.enable) { |
|||
console.log('webln enabled'); |
|||
this.setState({ weblnEnabled: true }); |
|||
} |
|||
}} |
|||
onLoadStart={e => { |
|||
alreadyInjected = false; |
|||
console.log('load start'); |
|||
this.setState({ pageIsLoading: true, weblnEnabled: false }); |
|||
}} |
|||
onLoadEnd={e => { |
|||
console.log('load end'); |
|||
this.setState({ url: e.nativeEvent.url, pageIsLoading: false }); |
|||
}} |
|||
/> |
|||
); |
|||
} |
|||
}; |
|||
render() { |
|||
return ( |
|||
<SafeBlueArea> |
|||
<View style={{ flexDirection: 'row', alignItems: 'center' }}> |
|||
<TouchableOpacity |
|||
onPress={() => { |
|||
this.webview.goBack(); |
|||
}} |
|||
> |
|||
<Ionicons |
|||
name={'ios-arrow-round-back'} |
|||
size={36} |
|||
style={{ |
|||
color: 'red', |
|||
backgroundColor: 'transparent', |
|||
paddingLeft: 10, |
|||
}} |
|||
/> |
|||
</TouchableOpacity> |
|||
|
|||
<FormInput |
|||
inputStyle={{ color: '#0c2550', maxWidth: width - 150, fontSize: 16 }} |
|||
containerStyle={{ |
|||
maxWidth: width - 150, |
|||
borderColor: '#d2d2d2', |
|||
borderWidth: 0.5, |
|||
backgroundColor: '#f5f5f5', |
|||
}} |
|||
value={this.state.url} |
|||
/> |
|||
|
|||
<TouchableOpacity |
|||
onPress={() => { |
|||
processedInvoices = {}; |
|||
this.setState({ url: 'https://bluewallet.io/marketplace/' }); |
|||
}} |
|||
> |
|||
<Ionicons |
|||
name={'ios-home'} |
|||
size={36} |
|||
style={{ |
|||
color: this.state.weblnEnabled ? 'green' : 'red', |
|||
backgroundColor: 'transparent', |
|||
}} |
|||
/> |
|||
</TouchableOpacity> |
|||
|
|||
<TouchableOpacity |
|||
onPress={() => { |
|||
let reloadUrl = this.state.url; |
|||
this.setState({ url: 'about:blank' }); |
|||
processedInvoices = {}; |
|||
setTimeout(() => this.setState({ url: reloadUrl }), 500); |
|||
// this.webview.reload();
|
|||
}} |
|||
> |
|||
{(!this.state.pageIsLoading && ( |
|||
<Ionicons |
|||
name={'ios-sync'} |
|||
size={36} |
|||
style={{ |
|||
color: 'red', |
|||
backgroundColor: 'transparent', |
|||
paddingLeft: 15, |
|||
}} |
|||
/> |
|||
)) || ( |
|||
<View style={{ paddingLeft: 20 }}> |
|||
<ActivityIndicator /> |
|||
</View> |
|||
)} |
|||
</TouchableOpacity> |
|||
</View> |
|||
{this.renderWebView()} |
|||
</SafeBlueArea> |
|||
); |
|||
} |
|||
} |
|||
|
|||
Browser.propTypes = { |
|||
navigation: PropTypes.shape({ |
|||
getParam: PropTypes.func, |
|||
navigate: PropTypes.func, |
|||
}), |
|||
}; |
@ -0,0 +1,51 @@ |
|||
import React, { Component } from 'react'; |
|||
import { ScrollView } from 'react-native'; |
|||
import { BlueLoading, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../../BlueComponents'; |
|||
import PropTypes from 'prop-types'; |
|||
/** @type {AppStorage} */ |
|||
const notes = require('../../release-notes'); |
|||
|
|||
export default class ReleaseNotes extends Component { |
|||
static navigationOptions = () => ({ |
|||
...BlueNavigationStyle(), |
|||
title: 'Release notes', |
|||
}); |
|||
|
|||
constructor(props) { |
|||
super(props); |
|||
this.state = { |
|||
isLoading: true, |
|||
}; |
|||
} |
|||
|
|||
async componentDidMount() { |
|||
console.log(notes); |
|||
this.setState({ |
|||
isLoading: false, |
|||
notes: notes, |
|||
}); |
|||
} |
|||
|
|||
render() { |
|||
if (this.state.isLoading) { |
|||
return <BlueLoading />; |
|||
} |
|||
|
|||
return ( |
|||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}> |
|||
<ScrollView> |
|||
<BlueCard> |
|||
<BlueText>{this.state.notes}</BlueText> |
|||
</BlueCard> |
|||
</ScrollView> |
|||
</SafeBlueArea> |
|||
); |
|||
} |
|||
} |
|||
|
|||
ReleaseNotes.propTypes = { |
|||
navigation: PropTypes.shape({ |
|||
navigate: PropTypes.func, |
|||
goBack: PropTypes.func, |
|||
}), |
|||
}; |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue