ADD: Apple Watch support
|
@ -67,4 +67,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
|||
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
|
||||
|
||||
[version]
|
||||
^0.86.0
|
||||
^0.97.0
|
||||
|
|
4
.gitignore
vendored
|
@ -57,4 +57,6 @@ buck-out/
|
|||
|
||||
#BlueWallet
|
||||
release-notes.json
|
||||
release-notes.txt
|
||||
release-notes.txt
|
||||
|
||||
ios/Pods/
|
||||
|
|
3
App.js
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Linking, AppState, Clipboard, StyleSheet, KeyboardAvoidingView, Platform, View, AsyncStorage } from 'react-native';
|
||||
import { Linking, AppState, Clipboard, StyleSheet, KeyboardAvoidingView, Platform, View } from 'react-native';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
import Modal from 'react-native-modal';
|
||||
import { NavigationActions } from 'react-navigation';
|
||||
import MainBottomTabs from './MainBottomTabs';
|
||||
|
|
22
App.test.js
|
@ -5,13 +5,11 @@ import TestRenderer from 'react-test-renderer';
|
|||
import Settings from './screen/settings/settings';
|
||||
import Selftest from './screen/selftest';
|
||||
import { BlueHeader } from './BlueComponents';
|
||||
import MockStorage from './MockStorage';
|
||||
import { FiatUnit } from './models/fiatUnit';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, but not in RN environment
|
||||
let assert = require('assert');
|
||||
jest.mock('react-native-qrcode-svg', () => 'Video');
|
||||
const AsyncStorage = new MockStorage();
|
||||
jest.setMock('AsyncStorage', AsyncStorage);
|
||||
jest.useFakeTimers();
|
||||
jest.mock('Picker', () => {
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
|
@ -105,7 +103,6 @@ it('Selftest work', () => {
|
|||
});
|
||||
|
||||
it('Appstorage - loadFromDisk works', async () => {
|
||||
AsyncStorage.storageCache = {}; // cleanup from other tests
|
||||
/** @type {AppStorage} */
|
||||
let Storage = new AppStorage();
|
||||
let w = new SegwitP2SHWallet();
|
||||
|
@ -125,16 +122,14 @@ it('Appstorage - loadFromDisk works', async () => {
|
|||
|
||||
// emulating encrypted storage (and testing flag)
|
||||
|
||||
AsyncStorage.storageCache.data = false;
|
||||
AsyncStorage.storageCache.data_encrypted = '1'; // flag
|
||||
await AsyncStorage.setItem('data', false);
|
||||
await AsyncStorage.setItem(AppStorage.FLAG_ENCRYPTED, '1');
|
||||
let Storage3 = new AppStorage();
|
||||
isEncrypted = await Storage3.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
});
|
||||
|
||||
it('Appstorage - encryptStorage & load encrypted storage works', async () => {
|
||||
AsyncStorage.storageCache = {}; // cleanup from other tests
|
||||
|
||||
/** @type {AppStorage} */
|
||||
let Storage = new AppStorage();
|
||||
let w = new SegwitP2SHWallet();
|
||||
|
@ -236,7 +231,7 @@ it('Wallet can fetch balance', async () => {
|
|||
assert.ok(w.getUnconfirmedBalance() === 0);
|
||||
assert.ok(w._lastBalanceFetch === 0);
|
||||
await w.fetchBalance();
|
||||
assert.ok(w.getBalance() === 0.18262);
|
||||
assert.ok(w.getBalance() === 18262000);
|
||||
assert.ok(w.getUnconfirmedBalance() === 0);
|
||||
assert.ok(w._lastBalanceFetch > 0);
|
||||
});
|
||||
|
@ -302,19 +297,18 @@ it('Wallet can fetch TXs', async () => {
|
|||
describe('currency', () => {
|
||||
it('fetches exchange rate and saves to AsyncStorage', async () => {
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 15000;
|
||||
AsyncStorage.storageCache = {}; // cleanup from other tests
|
||||
let currency = require('./currency');
|
||||
await currency.startUpdater();
|
||||
let cur = AsyncStorage.storageCache[AppStorage.EXCHANGE_RATES];
|
||||
let cur = await AsyncStorage.getItem(AppStorage.EXCHANGE_RATES);
|
||||
cur = JSON.parse(cur);
|
||||
assert.ok(Number.isInteger(cur[currency.STRUCT.LAST_UPDATED]));
|
||||
assert.ok(cur[currency.STRUCT.LAST_UPDATED] > 0);
|
||||
assert.ok(cur['BTC_USD'] > 0);
|
||||
|
||||
// now, setting other currency as default
|
||||
AsyncStorage.storageCache[AppStorage.PREFERRED_CURRENCY] = JSON.stringify(FiatUnit.JPY);
|
||||
await AsyncStorage.setItem(AppStorage.PREFERRED_CURRENCY, JSON.stringify(FiatUnit.JPY));
|
||||
await currency.startUpdater();
|
||||
cur = JSON.parse(AsyncStorage.storageCache[AppStorage.EXCHANGE_RATES]);
|
||||
cur = JSON.parse(await AsyncStorage.getItem(AppStorage.EXCHANGE_RATES));
|
||||
assert.ok(cur['BTC_JPY'] > 0);
|
||||
|
||||
// now setting with a proper setter
|
||||
|
@ -322,7 +316,7 @@ describe('currency', () => {
|
|||
await currency.startUpdater();
|
||||
let preferred = await currency.getPreferredCurrency();
|
||||
assert.strictEqual(preferred.endPointKey, 'EUR');
|
||||
cur = JSON.parse(AsyncStorage.storageCache[AppStorage.EXCHANGE_RATES]);
|
||||
cur = JSON.parse(await AsyncStorage.getItem(AppStorage.EXCHANGE_RATES));
|
||||
assert.ok(cur['BTC_EUR'] > 0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ let A = require('./analytics');
|
|||
let BlueElectrum = require('./BlueElectrum'); // eslint-disable-line
|
||||
|
||||
/** @type {AppStorage} */
|
||||
let BlueApp = new AppStorage();
|
||||
const BlueApp = new AppStorage();
|
||||
|
||||
async function startAndDecrypt(retry) {
|
||||
console.log('startAndDecrypt');
|
||||
|
|
|
@ -25,7 +25,6 @@ import {
|
|||
import LinearGradient from 'react-native-linear-gradient';
|
||||
import { LightningCustodianWallet } from './class';
|
||||
import Carousel from 'react-native-snap-carousel';
|
||||
import DeviceInfo from 'react-native-device-info';
|
||||
import { BitcoinUnit } from './models/bitcoinUnits';
|
||||
import NavigationService from './NavigationService';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
|
@ -36,6 +35,7 @@ let loc = require('./loc/');
|
|||
let BlueApp = require('./BlueApp');
|
||||
const { height, width } = Dimensions.get('window');
|
||||
const aspectRatio = height / width;
|
||||
const BigNumber = require('bignumber.js');
|
||||
let isIpad;
|
||||
if (aspectRatio > 1.6) {
|
||||
isIpad = false;
|
||||
|
@ -241,6 +241,14 @@ export class BlueCopyTextToClipboard extends Component {
|
|||
this.state = { hasTappedText: false, address: props.text };
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props, state) {
|
||||
if (state.hasTappedText) {
|
||||
return { hasTappedText: state.hasTappedText, address: state.address };
|
||||
} else {
|
||||
return { hasTappedText: state.hasTappedText, address: props.text };
|
||||
}
|
||||
}
|
||||
|
||||
copyToClipboard = () => {
|
||||
this.setState({ hasTappedText: true }, () => {
|
||||
Clipboard.setString(this.props.text);
|
||||
|
@ -404,29 +412,6 @@ export class BlueFormMultiInput extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
export class BlueFormInputAddress extends Component {
|
||||
render() {
|
||||
return (
|
||||
<FormInput
|
||||
{...this.props}
|
||||
inputStyle={{
|
||||
maxWidth: width - 110,
|
||||
color: BlueApp.settings.foregroundColor,
|
||||
fontSize: (isIpad && 10) || ((is.iphone8() && 12) || 14),
|
||||
}}
|
||||
containerStyle={{
|
||||
marginTop: 5,
|
||||
borderColor: BlueApp.settings.inputBorderColor,
|
||||
borderBottomColor: BlueApp.settings.inputBorderColor,
|
||||
borderWidth: 0.5,
|
||||
borderBottomWidth: 0.5,
|
||||
backgroundColor: BlueApp.settings.inputBackgroundColor,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class BlueHeader extends Component {
|
||||
render() {
|
||||
return (
|
||||
|
@ -560,13 +545,6 @@ export class is {
|
|||
static ipad() {
|
||||
return isIpad;
|
||||
}
|
||||
|
||||
static iphone8() {
|
||||
if (Platform.OS !== 'ios') {
|
||||
return false;
|
||||
}
|
||||
return DeviceInfo.getDeviceId() === 'iPhone10,4';
|
||||
}
|
||||
}
|
||||
|
||||
export class BlueSpacing20 extends Component {
|
||||
|
@ -1733,7 +1711,7 @@ export class BlueAddressInput extends Component {
|
|||
export class BlueBitcoinAmount extends Component {
|
||||
static propTypes = {
|
||||
isLoading: PropTypes.bool,
|
||||
amount: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
amount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
||||
onChangeText: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
unit: PropTypes.string,
|
||||
|
@ -1744,8 +1722,15 @@ export class BlueBitcoinAmount extends Component {
|
|||
};
|
||||
|
||||
render() {
|
||||
const amount = typeof this.props.amount === 'number' ? this.props.amount.toString() : this.props.amount;
|
||||
|
||||
const amount = this.props.amount || 0;
|
||||
let localCurrency = loc.formatBalanceWithoutSuffix(amount, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
if (this.props.unit === BitcoinUnit.BTC) {
|
||||
let sat = new BigNumber(amount);
|
||||
sat = sat.multipliedBy(100000000).toString();
|
||||
localCurrency = loc.formatBalanceWithoutSuffix(sat, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
} else {
|
||||
localCurrency = loc.formatBalanceWithoutSuffix(amount.toString(), BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
}
|
||||
return (
|
||||
<TouchableWithoutFeedback disabled={this.props.pointerEvents === 'none'} onPress={() => this.textInput.focus()}>
|
||||
<View>
|
||||
|
@ -1788,13 +1773,7 @@ export class BlueBitcoinAmount extends Component {
|
|||
</Text>
|
||||
</View>
|
||||
<View style={{ alignItems: 'center', marginBottom: 22, marginTop: 4 }}>
|
||||
<Text style={{ fontSize: 18, color: '#d4d4d4', fontWeight: '600' }}>
|
||||
{loc.formatBalance(
|
||||
this.props.unit === BitcoinUnit.BTC ? amount || 0 : loc.formatBalanceWithoutSuffix(amount || 0, BitcoinUnit.BTC, false),
|
||||
BitcoinUnit.LOCAL_CURRENCY,
|
||||
false,
|
||||
)}
|
||||
</Text>
|
||||
<Text style={{ fontSize: 18, color: '#d4d4d4', fontWeight: '600' }}>{localCurrency}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { AsyncStorage } from 'react-native';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
const ElectrumClient = require('electrum-client');
|
||||
let bitcoin = require('bitcoinjs-lib');
|
||||
let reverse = require('buffer-reverse');
|
||||
|
||||
const storageKey = 'ELECTRUM_PEERS';
|
||||
const defaultPeer = { host: 'electrum1.bluewallet.io', tcp: 50001 };
|
||||
const defaultPeer = { host: 'electrum1.bluewallet.io', tcp: '50001' };
|
||||
const hardcodedPeers = [
|
||||
// { host: 'noveltybobble.coinjoined.com', tcp: '50001' }, // down
|
||||
// { host: 'electrum.be', tcp: '50001' },
|
||||
|
@ -170,8 +170,8 @@ async function waitTillConnected() {
|
|||
async function estimateFees() {
|
||||
if (!mainClient) throw new Error('Electrum client is not connected');
|
||||
const fast = await mainClient.blockchainEstimatefee(1);
|
||||
const medium = await mainClient.blockchainEstimatefee(6);
|
||||
const slow = await mainClient.blockchainEstimatefee(12);
|
||||
const medium = await mainClient.blockchainEstimatefee(5);
|
||||
const slow = await mainClient.blockchainEstimatefee(10);
|
||||
return { fast, medium, slow };
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ beforeAll(async () => {
|
|||
// while app starts up, but for tests we need to wait for it
|
||||
try {
|
||||
await BlueElectrum.waitTillConnected();
|
||||
} catch (Err) {
|
||||
console.log('failed to connect to Electrum:', Err);
|
||||
} catch (err) {
|
||||
console.log('failed to connect to Electrum:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
@ -52,7 +52,6 @@ describe('Electrum', () => {
|
|||
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);
|
||||
|
|
|
@ -207,7 +207,7 @@ it('Segwit HD (BIP49) can fetch balance with many used addresses in hierarchy',
|
|||
let end = +new Date();
|
||||
const took = (end - start) / 1000;
|
||||
took > 15 && console.warn('took', took, "sec to fetch huge HD wallet's balance");
|
||||
assert.strictEqual(hd.getBalance(), 0.00051432);
|
||||
assert.strictEqual(hd.getBalance(), 51432);
|
||||
|
||||
await hd.fetchUtxo();
|
||||
assert.ok(hd.utxo.length > 0);
|
||||
|
|
138
WatchConnectivity.js
Normal file
|
@ -0,0 +1,138 @@
|
|||
import * as watch from 'react-native-watch-connectivity';
|
||||
import { InteractionManager } from 'react-native';
|
||||
const loc = require('./loc');
|
||||
export default class WatchConnectivity {
|
||||
isAppInstalled = false;
|
||||
BlueApp = require('./BlueApp');
|
||||
|
||||
constructor() {
|
||||
this.getIsWatchAppInstalled();
|
||||
}
|
||||
|
||||
getIsWatchAppInstalled() {
|
||||
watch.getIsWatchAppInstalled((err, isAppInstalled) => {
|
||||
if (!err) {
|
||||
this.isAppInstalled = isAppInstalled;
|
||||
this.sendWalletsToWatch();
|
||||
}
|
||||
});
|
||||
watch.subscribeToMessages(async (err, message, reply) => {
|
||||
if (!err) {
|
||||
if (message.request === 'createInvoice') {
|
||||
const createInvoiceRequest = await this.handleLightningInvoiceCreateRequest(
|
||||
message.walletIndex,
|
||||
message.amount,
|
||||
message.description,
|
||||
);
|
||||
reply({ invoicePaymentRequest: createInvoiceRequest });
|
||||
}
|
||||
} else {
|
||||
reply(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async handleLightningInvoiceCreateRequest(walletIndex, amount, description) {
|
||||
const wallet = this.BlueApp.getWallets()[walletIndex];
|
||||
if (wallet.allowReceive() && amount > 0 && description.trim().length > 0) {
|
||||
try {
|
||||
const invoiceRequest = await wallet.addInvoice(amount, description);
|
||||
return invoiceRequest;
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async sendWalletsToWatch() {
|
||||
InteractionManager.runAfterInteractions(async () => {
|
||||
if (this.isAppInstalled) {
|
||||
const allWallets = this.BlueApp.getWallets();
|
||||
let wallets = [];
|
||||
for (const wallet of allWallets) {
|
||||
let receiveAddress = '';
|
||||
if (wallet.allowReceive()) {
|
||||
if (wallet.getAddressAsync) {
|
||||
receiveAddress = await wallet.getAddressAsync();
|
||||
} else {
|
||||
receiveAddress = wallet.getAddress();
|
||||
}
|
||||
}
|
||||
let transactions = wallet.getTransactions(10);
|
||||
let watchTransactions = [];
|
||||
for (const transaction of transactions) {
|
||||
let type = 'pendingConfirmation';
|
||||
let memo = '';
|
||||
let amount = 0;
|
||||
|
||||
if (transaction.hasOwnProperty('confirmations') && !transaction.confirmations > 0) {
|
||||
type = 'pendingConfirmation';
|
||||
} else if (transaction.type === 'user_invoice' || transaction.type === 'payment_request') {
|
||||
const currentDate = new Date();
|
||||
const now = (currentDate.getTime() / 1000) | 0;
|
||||
const invoiceExpiration = transaction.timestamp + transaction.expire_time;
|
||||
|
||||
if (invoiceExpiration > now) {
|
||||
type = 'pendingConfirmation';
|
||||
} else if (invoiceExpiration < now) {
|
||||
if (transaction.ispaid) {
|
||||
type = 'received';
|
||||
} else {
|
||||
type = 'sent';
|
||||
}
|
||||
}
|
||||
} else if (transaction.value / 100000000 < 0) {
|
||||
type = 'sent';
|
||||
} else {
|
||||
type = 'received';
|
||||
}
|
||||
if (transaction.type === 'user_invoice' || transaction.type === 'payment_request') {
|
||||
if (isNaN(transaction.value)) {
|
||||
amount = '0';
|
||||
}
|
||||
const currentDate = new Date();
|
||||
const now = (currentDate.getTime() / 1000) | 0;
|
||||
const invoiceExpiration = transaction.timestamp + transaction.expire_time;
|
||||
|
||||
if (invoiceExpiration > now) {
|
||||
amount = loc.formatBalance(transaction.value, wallet.getPreferredBalanceUnit(), true).toString();
|
||||
} else if (invoiceExpiration < now) {
|
||||
if (transaction.ispaid) {
|
||||
amount = loc.formatBalance(transaction.value, wallet.getPreferredBalanceUnit(), true).toString();
|
||||
} else {
|
||||
amount = loc.lnd.expired;
|
||||
}
|
||||
} else {
|
||||
amount = loc.formatBalance(transaction.value, wallet.getPreferredBalanceUnit(), true).toString();
|
||||
}
|
||||
} else {
|
||||
amount = loc.formatBalance(transaction.value, wallet.getPreferredBalanceUnit(), true).toString();
|
||||
}
|
||||
if (this.BlueApp.tx_metadata[transaction.hash] && this.BlueApp.tx_metadata[transaction.hash]['memo']) {
|
||||
memo = this.BlueApp.tx_metadata[transaction.hash]['memo'];
|
||||
} else if (transaction.memo) {
|
||||
memo = transaction.memo;
|
||||
}
|
||||
const watchTX = { type, amount, memo, time: loc.transactionTimeToReadable(transaction.received) };
|
||||
watchTransactions.push(watchTX);
|
||||
}
|
||||
wallets.push({
|
||||
label: wallet.getLabel(),
|
||||
balance: loc.formatBalance(Number(wallet.getBalance()), wallet.getPreferredBalanceUnit(), true),
|
||||
type: wallet.type,
|
||||
preferredBalanceUnit: wallet.getPreferredBalanceUnit(),
|
||||
receiveAddress: receiveAddress,
|
||||
transactions: watchTransactions,
|
||||
});
|
||||
}
|
||||
|
||||
watch.updateApplicationContext({ wallets });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
WatchConnectivity.init = function() {
|
||||
if (WatchConnectivity.shared) return;
|
||||
WatchConnectivity.shared = new WatchConnectivity();
|
||||
};
|
1
__mocks__/@react-native-community/async-storage.js
Normal file
|
@ -0,0 +1 @@
|
|||
export default from '@react-native-community/async-storage/jest/async-storage-mock'
|
|
@ -17,7 +17,7 @@
|
|||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res;file://$MODULE_DIR$/build/generated/res/rs/debug;file://$MODULE_DIR$/build/generated/res/resValues/debug" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||
</configuration>
|
||||
</facet>
|
||||
|
@ -28,16 +28,16 @@
|
|||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debug/compileDebugAidl/out" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debug/compileDebugRenderscript/out" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/react/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debugAndroidTest/compileDebugAndroidTestAidl/out" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debugAndroidTest/compileDebugAndroidTestRenderscript/out" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" />
|
||||
|
@ -48,13 +48,6 @@
|
|||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/assets" type="java-test-resource" />
|
||||
|
@ -62,6 +55,13 @@
|
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/rs" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/shaders" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
||||
|
@ -87,103 +87,106 @@
|
|||
<excludeFolder url="file://$MODULE_DIR$/build/generated/source/r" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotation_processor_list" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/apk_list" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/build-info" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-libraries" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-manifest" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/checkDebugClasspath" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/checkReleaseClasspath" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundle_manifest" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check_manifest_result" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/compatible_screen_manifest" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/external_libs_dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-apk" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_main_apk_resources" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_app_manifest" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_merged_manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_split_apk_resources" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaPrecompile" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javac" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/legacy_multidex_aapt_derived_proguard_rules" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/legacy_multidex_main_dex_list" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/linked_res_for_bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint_jar" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifest-checker" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/module_bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/metadata_feature_manifest" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/processed_res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/resources" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shader_assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split-apk" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split_list" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/splits-support" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/signing_config" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/validate_signing_config" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 27 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Gradle: org.webkit:android-jsc:r174650@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-vector-drawable:27.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp-urlconnection:3.12.1@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:fresco:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.react:react-native:0.57.8@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-core:1.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-core-utils:27.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime:1.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-fragment:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:localbroadcastmanager:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:fbcore:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:viewmodel:1.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:animated-vector-drawable:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:drawee:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp:3.11.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.parse.bolts:bolts-tasks:1.4.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:exifinterface:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-v4:27.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.core:runtime:1.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp-urlconnection:3.11.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:animated-vector-drawable:27.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-okhttp3:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:viewmodel:1.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp:3.12.1@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:loader:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.core:runtime:1.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-core:1.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:cursoradapter:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime:1.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-compat:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-base:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: io.sentry:sentry:1.7.5@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.squareup.okio:okio:1.14.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.zxing:core:3.3.3@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: javax.inject:javax.inject:1@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-core-ui:27.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-compat:27.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.soloader:soloader:0.6.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.code.findbugs:jsr305:3.0.2@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-vector-drawable:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-core-utils:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-annotations:28.0.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:interpolator:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata:1.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:drawerlayout:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:documentfile:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:slidingpanelayout:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.parse.bolts:bolts-tasks:1.4.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:appcompat-v7:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: com.android.support:multidex-instrumentation:1.0.2@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:collections:28.0.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-core-ui:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-okhttp3:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:asynclayoutinflater:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:print:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.core:common:1.1.1@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:versionedparcelable:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.infer.annotation:infer-annotation:0.11.2@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.slf4j:slf4j-api:1.7.24@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-media-compat:27.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.code.findbugs:jsr305:3.0.2@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-fragment:27.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: io.sentry:sentry-android:1.7.5@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-annotations:28.0.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:appcompat-v7:27.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.core:common:1.1.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.fasterxml.jackson.core:jackson-core:2.8.7@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.soloader:soloader:0.5.1@aar" level="project" />
|
||||
<orderEntry type="module" module-name="react-native-webview" />
|
||||
<orderEntry type="module" module-name="react-native-linear-gradient" />
|
||||
<orderEntry type="module" module-name="react-native-svg" />
|
||||
<orderEntry type="module" module-name="react-native-sentry" />
|
||||
<orderEntry type="module" module-name="react-native-google-analytics-bridge" />
|
||||
<orderEntry type="module" module-name="react-native-haptic-feedback" />
|
||||
<orderEntry type="module" module-name="react-native-gesture-handler" />
|
||||
<orderEntry type="module" module-name="react-native-fs" />
|
||||
<orderEntry type="module" module-name="react-native-prompt-android" />
|
||||
<orderEntry type="module" module-name="react-native-vector-icons" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:viewpager:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.react:react-native:0.59.6@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.1@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:coordinatorlayout:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:customview:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:swiperefreshlayout:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:multidex:1.0.3@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.squareup.okio:okio:1.15.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.koushikdutta.async:androidasync:2.1.6@jar" level="project" />
|
||||
<orderEntry type="module" module-name="react-native-device-info" />
|
||||
<orderEntry type="module" module-name="react-native-randombytes" />
|
||||
<orderEntry type="module" module-name="react-native-google-analytics-bridge" />
|
||||
<orderEntry type="module" module-name="react-native-obscure" />
|
||||
<orderEntry type="module" module-name="react-native-camera" />
|
||||
<orderEntry type="module" module-name="react-native-webview" />
|
||||
<orderEntry type="module" module-name="@react-native-community_slider" />
|
||||
<orderEntry type="module" module-name="react-native-sentry" />
|
||||
<orderEntry type="module" module-name="react-native-linear-gradient" />
|
||||
<orderEntry type="module" module-name="react-native-image-picker" />
|
||||
<orderEntry type="module" module-name="react-native-vector-icons" />
|
||||
<orderEntry type="module" module-name="react-native-haptic-feedback" />
|
||||
<orderEntry type="module" module-name="@react-native-community_async-storage" />
|
||||
<orderEntry type="module" module-name="react-native-prompt-android" />
|
||||
<orderEntry type="module" module-name="react-native-gesture-handler" />
|
||||
<orderEntry type="module" module-name="react-native-randombytes" />
|
||||
<orderEntry type="module" module-name="react-native-svg" />
|
||||
<orderEntry type="module" module-name="@remobile_react-native-qrcode-local-image" />
|
||||
<orderEntry type="module" module-name="react-native-fs" />
|
||||
<orderEntry type="module" module-name="react-native-tcp" />
|
||||
<orderEntry type="library" name="Gradle: android-android-27" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -102,7 +102,7 @@ android {
|
|||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "3.9.7"
|
||||
versionName "3.9.8"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
}
|
||||
|
@ -139,6 +139,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':@react-native-community_async-storage')
|
||||
implementation project(':@react-native-community_slider')
|
||||
implementation project(':react-native-obscure')
|
||||
implementation project(':react-native-tcp')
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.bluewallet.bluewallet;
|
|||
import android.app.Application;
|
||||
|
||||
import com.facebook.react.ReactApplication;
|
||||
import com.reactnativecommunity.asyncstorage.AsyncStoragePackage;
|
||||
import com.reactnativecommunity.slider.ReactSliderPackage;
|
||||
import com.diegofhg.obscure.ObscurePackage;
|
||||
import com.peel.react.TcpSocketsModule;
|
||||
|
@ -58,6 +59,7 @@ public class MainApplication extends Application implements ReactApplication {
|
|||
protected List<ReactPackage> getPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new MainReactPackage(),
|
||||
new AsyncStoragePackage(),
|
||||
new ReactSliderPackage(),
|
||||
new ObscurePackage(),
|
||||
new TcpSocketsModule(),
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
rootProject.name = 'BlueWallet'
|
||||
include ':@react-native-community_async-storage'
|
||||
project(':@react-native-community_async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android')
|
||||
include ':@react-native-community_slider'
|
||||
project(':@react-native-community_slider').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/slider/android')
|
||||
include ':react-native-obscure'
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { LegacyWallet } from './legacy-wallet';
|
||||
import Frisbee from 'frisbee';
|
||||
const bip39 = require('bip39');
|
||||
const BigNumber = require('bignumber.js');
|
||||
const bitcoin = require('bitcoinjs-lib');
|
||||
const BlueElectrum = require('../BlueElectrum');
|
||||
|
||||
|
@ -421,8 +420,8 @@ export class AbstractHDWallet extends LegacyWallet {
|
|||
|
||||
// finally fetching balance
|
||||
let balance = await BlueElectrum.multiGetBalanceByAddress(this.usedAddresses);
|
||||
this.balance = new BigNumber(balance.balance).dividedBy(100000000).toNumber();
|
||||
this.unconfirmed_balance = new BigNumber(balance.unconfirmed_balance).dividedBy(100000000).toNumber();
|
||||
this.balance = balance.balance;
|
||||
this.unconfirmed_balance = balance.unconfirmed_balance;
|
||||
this._lastBalanceFetch = +new Date();
|
||||
} catch (err) {
|
||||
console.warn(err);
|
||||
|
|
|
@ -95,7 +95,5 @@ export class AbstractWallet {
|
|||
return 0;
|
||||
}
|
||||
|
||||
getAddress() {}
|
||||
|
||||
// createTx () { throw Error('not implemented') }
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { AsyncStorage } from 'react-native';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
import {
|
||||
HDLegacyBreadwalletWallet,
|
||||
HDSegwitP2SHWallet,
|
||||
|
@ -9,7 +9,8 @@ import {
|
|||
SegwitBech32Wallet,
|
||||
} from './';
|
||||
import { LightningCustodianWallet } from './lightning-custodian-wallet';
|
||||
let encryption = require('../encryption');
|
||||
import WatchConnectivity from '../WatchConnectivity';
|
||||
const encryption = require('../encryption');
|
||||
|
||||
export class AppStorage {
|
||||
static FLAG_ENCRYPTED = 'data_encrypted';
|
||||
|
@ -118,8 +119,9 @@ export class AppStorage {
|
|||
buckets = JSON.parse(buckets);
|
||||
buckets.push(encryption.encrypt(JSON.stringify(data), fakePassword));
|
||||
this.cachedPassword = fakePassword;
|
||||
|
||||
return AsyncStorage.setItem('data', JSON.stringify(buckets));
|
||||
const bucketsString = JSON.stringify(buckets);
|
||||
await AsyncStorage.setItem('data', bucketsString);
|
||||
return (await AsyncStorage.getItem('data')) === bucketsString;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,6 +201,8 @@ export class AppStorage {
|
|||
this.tx_metadata = data.tx_metadata;
|
||||
}
|
||||
}
|
||||
WatchConnectivity.init();
|
||||
await WatchConnectivity.shared.sendWalletsToWatch();
|
||||
return true;
|
||||
} else {
|
||||
return false; // failed loading data or loading/decryptin data
|
||||
|
@ -269,7 +273,8 @@ export class AppStorage {
|
|||
} else {
|
||||
await AsyncStorage.setItem(AppStorage.FLAG_ENCRYPTED, ''); // drop the flag
|
||||
}
|
||||
|
||||
WatchConnectivity.init();
|
||||
WatchConnectivity.shared.sendWalletsToWatch();
|
||||
return AsyncStorage.setItem('data', JSON.stringify(data));
|
||||
}
|
||||
|
||||
|
|
|
@ -114,8 +114,7 @@ export class LegacyWallet extends AbstractWallet {
|
|||
throw new Error('Could not fetch balance from API: ' + response.err + ' ' + JSON.stringify(response.body));
|
||||
}
|
||||
|
||||
this.balance = new BigNumber(json.final_balance);
|
||||
this.balance = this.balance.dividedBy(100000000).toString() * 1;
|
||||
this.balance = Number(json.final_balance);
|
||||
this.unconfirmed_balance = new BigNumber(json.unconfirmed_balance);
|
||||
this.unconfirmed_balance = this.unconfirmed_balance.dividedBy(100000000).toString() * 1;
|
||||
this._lastBalanceFetch = +new Date();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { LegacyWallet } from './legacy-wallet';
|
||||
import Frisbee from 'frisbee';
|
||||
import { BitcoinUnit, Chain } from '../models/bitcoinUnits';
|
||||
let BigNumber = require('bignumber.js');
|
||||
|
||||
export class LightningCustodianWallet extends LegacyWallet {
|
||||
static type = 'lightningCustodianWallet';
|
||||
|
@ -455,7 +454,7 @@ export class LightningCustodianWallet extends LegacyWallet {
|
|||
}
|
||||
|
||||
getBalance() {
|
||||
return new BigNumber(this.balance).dividedBy(100000000).toString(10);
|
||||
return this.balance;
|
||||
}
|
||||
|
||||
async fetchBalance(noRetry) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Frisbee from 'frisbee';
|
||||
import { AsyncStorage } from 'react-native';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
import { AppStorage } from './class';
|
||||
import { FiatUnit } from './models/fiatUnit';
|
||||
let BigNumber = require('bignumber.js');
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1010"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "NO"
|
||||
|
|
|
@ -1,25 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1010"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "NO"
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
|
||||
BuildableName = "libReact.a"
|
||||
BlueprintName = "React"
|
||||
ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
|
@ -34,20 +20,6 @@
|
|||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||
BuildableName = "BlueWalletTests.xctest"
|
||||
BlueprintName = "BlueWalletTests"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B40D4E2F225841EC00428FCC"
|
||||
BuildableName = "BlueWalletWatch.app"
|
||||
BlueprintName = "BlueWalletWatch"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "BlueWallet.app"
|
||||
BlueprintName = "BlueWallet"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B40D4E2F225841EC00428FCC"
|
||||
BuildableName = "BlueWalletWatch.app"
|
||||
BlueprintName = "BlueWalletWatch"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
launchAutomaticallySubstyle = "8"
|
||||
notificationPayloadFile = "BlueWalletWatch Extension/PushNotificationPayload.apns">
|
||||
<RemoteRunnable
|
||||
runnableDebuggingMode = "2"
|
||||
BundleIdentifier = "com.apple.Carousel"
|
||||
RemotePath = "/BlueWallet">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B40D4E2F225841EC00428FCC"
|
||||
BuildableName = "BlueWalletWatch.app"
|
||||
BlueprintName = "BlueWalletWatch"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</RemoteRunnable>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B40D4E2F225841EC00428FCC"
|
||||
BuildableName = "BlueWalletWatch.app"
|
||||
BlueprintName = "BlueWalletWatch"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
launchAutomaticallySubstyle = "8"
|
||||
notificationPayloadFile = "BlueWalletWatch Extension/PushNotificationPayload.apns">
|
||||
<RemoteRunnable
|
||||
runnableDebuggingMode = "2"
|
||||
BundleIdentifier = "com.apple.Carousel"
|
||||
RemotePath = "/BlueWallet">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B40D4E2F225841EC00428FCC"
|
||||
BuildableName = "BlueWalletWatch.app"
|
||||
BlueprintName = "BlueWalletWatch"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</RemoteRunnable>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B40D4E2F225841EC00428FCC"
|
||||
BuildableName = "BlueWalletWatch.app"
|
||||
BlueprintName = "BlueWalletWatch"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
|
@ -0,0 +1,128 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B40D4E2F225841EC00428FCC"
|
||||
BuildableName = "BlueWalletWatch.app"
|
||||
BlueprintName = "BlueWalletWatch"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "BlueWallet.app"
|
||||
BlueprintName = "BlueWallet"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B40D4E2F225841EC00428FCC"
|
||||
BuildableName = "BlueWalletWatch.app"
|
||||
BlueprintName = "BlueWalletWatch"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
notificationPayloadFile = "BlueWalletWatch Extension/PushNotificationPayload.apns">
|
||||
<RemoteRunnable
|
||||
runnableDebuggingMode = "2"
|
||||
BundleIdentifier = "com.apple.Carousel"
|
||||
RemotePath = "/BlueWallet">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B40D4E2F225841EC00428FCC"
|
||||
BuildableName = "BlueWalletWatch.app"
|
||||
BlueprintName = "BlueWalletWatch"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</RemoteRunnable>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B40D4E2F225841EC00428FCC"
|
||||
BuildableName = "BlueWalletWatch.app"
|
||||
BlueprintName = "BlueWalletWatch"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<RemoteRunnable
|
||||
runnableDebuggingMode = "2"
|
||||
BundleIdentifier = "com.apple.Carousel"
|
||||
RemotePath = "/BlueWallet">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B40D4E2F225841EC00428FCC"
|
||||
BuildableName = "BlueWalletWatch.app"
|
||||
BlueprintName = "BlueWalletWatch"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</RemoteRunnable>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B40D4E2F225841EC00428FCC"
|
||||
BuildableName = "BlueWalletWatch.app"
|
||||
BlueprintName = "BlueWalletWatch"
|
||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
|
@ -4,16 +4,59 @@
|
|||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>BlueWallet-tvOS.xcscheme_^#shared#^_</key>
|
||||
<key>BlueWallet for Apple Watch (Notification).xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
<integer>78</integer>
|
||||
</dict>
|
||||
<key>BlueWallet.xcscheme_^#shared#^_</key>
|
||||
<key>BlueWallet for Apple Watch.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>71</integer>
|
||||
</dict>
|
||||
<key>BlueWallet-tvOS.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>BlueWallet.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>BlueWalletWatch (Glance).xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>14</integer>
|
||||
</dict>
|
||||
<key>BlueWalletWatch (Notification).xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>3</integer>
|
||||
</dict>
|
||||
<key>BlueWalletWatch.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>00E356ED1AD99517003FC87E</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>13B07F861A680F5B00A75B9A</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>B40D4E2F225841EC00428FCC</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
19
ios/BlueWallet.xcworkspace/contents.xcworkspacedata
generated
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:BlueWallet.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:../node_modules/react-native-tcp/ios/TcpSockets.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:../node_modules/@remobile/react-native-qrcode-local-image/ios/RCTQRCodeLocalImage.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:../node_modules/react-native-privacy-snapshot/RCTPrivacySnapshot.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -6,9 +6,13 @@
|
|||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
@import WatchConnectivity;
|
||||
@class WatchBridge;
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate, WCSessionDelegate>
|
||||
|
||||
@property (nonatomic, strong) UIWindow *window;
|
||||
@property(nonatomic, strong) WatchBridge *watchBridge;
|
||||
@property(nonatomic, strong) WCSession *session;
|
||||
|
||||
@end
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#else
|
||||
#import "RNSentry.h" // This is used for versions of react < 0.40
|
||||
#endif
|
||||
#import "WatchBridge.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
@ -35,6 +36,11 @@
|
|||
rootViewController.view = rootView;
|
||||
self.window.rootViewController = rootViewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
self.watchBridge = [WatchBridge shared];
|
||||
self.session = self.watchBridge.session;
|
||||
[self.session activateSession];
|
||||
self.session.delegate = self;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
@ -46,4 +52,18 @@
|
|||
return NO;
|
||||
}
|
||||
|
||||
- (void)sessionDidDeactivate:(WCSession *)session {
|
||||
[session activateSession];
|
||||
}
|
||||
|
||||
- (void)session:(nonnull WCSession *)session activationDidCompleteWithState:(WCSessionActivationState)activationState error:(nullable NSError *)error {
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (void)sessionDidBecomeInactive:(nonnull WCSession *)session {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.9.7</string>
|
||||
<string>3.9.8</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
|
56
ios/BlueWalletWatch Extension/ExtensionDelegate.swift
Normal file
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// ExtensionDelegate.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/6/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
import WatchKit
|
||||
|
||||
class ExtensionDelegate: NSObject, WKExtensionDelegate {
|
||||
|
||||
func applicationDidFinishLaunching() {
|
||||
// Perform any final initialization of your application.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive() {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillResignActive() {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, etc.
|
||||
}
|
||||
|
||||
func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
|
||||
// Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one.
|
||||
for task in backgroundTasks {
|
||||
// Use a switch statement to check the task type
|
||||
switch task {
|
||||
case let backgroundTask as WKApplicationRefreshBackgroundTask:
|
||||
// Be sure to complete the background task once you’re done.
|
||||
backgroundTask.setTaskCompletedWithSnapshot(false)
|
||||
case let snapshotTask as WKSnapshotRefreshBackgroundTask:
|
||||
// Snapshot tasks have a unique completion call, make sure to set your expiration date
|
||||
snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil)
|
||||
case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask:
|
||||
// Be sure to complete the connectivity task once you’re done.
|
||||
connectivityTask.setTaskCompletedWithSnapshot(false)
|
||||
case let urlSessionTask as WKURLSessionRefreshBackgroundTask:
|
||||
// Be sure to complete the URL session task once you’re done.
|
||||
urlSessionTask.setTaskCompletedWithSnapshot(false)
|
||||
case let relevantShortcutTask as WKRelevantShortcutRefreshBackgroundTask:
|
||||
// Be sure to complete the relevant-shortcut task once you're done.
|
||||
relevantShortcutTask.setTaskCompletedWithSnapshot(false)
|
||||
case let intentDidRunTask as WKIntentDidRunRefreshBackgroundTask:
|
||||
// Be sure to complete the intent-did-run task once you're done.
|
||||
intentDidRunTask.setTaskCompletedWithSnapshot(false)
|
||||
default:
|
||||
// make sure to complete unhandled task types
|
||||
task.setTaskCompletedWithSnapshot(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
38
ios/BlueWalletWatch Extension/Info.plist
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>BlueWalletWatch Extension</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.9.8</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>239</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string></string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionAttributes</key>
|
||||
<dict>
|
||||
<key>WKAppBundleIdentifier</key>
|
||||
<string>io.bluewallet.bluewallet.watch</string>
|
||||
</dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.watchkit</string>
|
||||
</dict>
|
||||
<key>WKExtensionDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).ExtensionDelegate</string>
|
||||
</dict>
|
||||
</plist>
|
57
ios/BlueWalletWatch Extension/InterfaceController.swift
Normal file
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// InterfaceController.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/6/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
import WatchKit
|
||||
import WatchConnectivity
|
||||
import Foundation
|
||||
|
||||
class InterfaceController: WKInterfaceController {
|
||||
|
||||
@IBOutlet weak var walletsTable: WKInterfaceTable!
|
||||
@IBOutlet weak var loadingIndicatorGroup: WKInterfaceGroup!
|
||||
@IBOutlet weak var noWalletsAvailableLabel: WKInterfaceLabel!
|
||||
|
||||
override func willActivate() {
|
||||
// This method is called when watch view controller is about to be visible to user
|
||||
super.willActivate()
|
||||
WCSession.default.sendMessage(["message" : "sendApplicationContext"], replyHandler: nil, errorHandler: nil)
|
||||
|
||||
if (WatchDataSource.shared.wallets.isEmpty) {
|
||||
loadingIndicatorGroup.setHidden(true)
|
||||
noWalletsAvailableLabel.setHidden(false)
|
||||
} else {
|
||||
processWalletsTable()
|
||||
}
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(processWalletsTable), name: WatchDataSource.NotificationName.dataUpdated, object: nil)
|
||||
}
|
||||
|
||||
@objc private func processWalletsTable() {
|
||||
loadingIndicatorGroup.setHidden(false)
|
||||
walletsTable.setHidden(true)
|
||||
walletsTable.setNumberOfRows(WatchDataSource.shared.wallets.count, withRowType: WalletInformation.identifier)
|
||||
|
||||
for index in 0..<walletsTable.numberOfRows {
|
||||
guard let controller = walletsTable.rowController(at: index) as? WalletInformation else { continue }
|
||||
let wallet = WatchDataSource.shared.wallets[index]
|
||||
if wallet.identifier == nil {
|
||||
WatchDataSource.shared.wallets[index].identifier = index
|
||||
}
|
||||
controller.name = wallet.label
|
||||
controller.balance = wallet.balance
|
||||
controller.type = WalletGradient(rawValue: wallet.type) ?? .SegwitHD
|
||||
}
|
||||
loadingIndicatorGroup.setHidden(true)
|
||||
noWalletsAvailableLabel.setHidden(!WatchDataSource.shared.wallets.isEmpty)
|
||||
walletsTable.setHidden(WatchDataSource.shared.wallets.isEmpty)
|
||||
}
|
||||
|
||||
override func contextForSegue(withIdentifier segueIdentifier: String, in table: WKInterfaceTable, rowIndex: Int) -> Any? {
|
||||
return rowIndex;
|
||||
}
|
||||
|
||||
}
|
38
ios/BlueWalletWatch Extension/NotificationController.swift
Normal file
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// NotificationController.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/6/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
import WatchKit
|
||||
import Foundation
|
||||
import UserNotifications
|
||||
|
||||
|
||||
class NotificationController: WKUserNotificationInterfaceController {
|
||||
|
||||
override init() {
|
||||
// Initialize variables here.
|
||||
super.init()
|
||||
|
||||
// Configure interface objects here.
|
||||
}
|
||||
|
||||
override func willActivate() {
|
||||
// This method is called when watch view controller is about to be visible to user
|
||||
super.willActivate()
|
||||
}
|
||||
|
||||
override func didDeactivate() {
|
||||
// This method is called when watch view controller is no longer visible
|
||||
super.didDeactivate()
|
||||
}
|
||||
|
||||
override func didReceive(_ notification: UNNotification) {
|
||||
// This method is called when a notification needs to be presented.
|
||||
// Implement it if you use a dynamic notification interface.
|
||||
// Populate your dynamic notification interface as quickly as possible.
|
||||
}
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
//
|
||||
// NumericKeypadInterfaceController.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/23/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
import WatchKit
|
||||
import Foundation
|
||||
|
||||
|
||||
class NumericKeypadInterfaceController: WKInterfaceController {
|
||||
|
||||
static let identifier = "NumericKeypadInterfaceController"
|
||||
private var amount: [String] = ["0"]
|
||||
var keyPadType: NumericKeypadType = .BTC
|
||||
struct NotificationName {
|
||||
static let keypadDataChanged = Notification.Name(rawValue: "Notification.NumericKeypadInterfaceController.keypadDataChanged")
|
||||
}
|
||||
struct Notifications {
|
||||
static let keypadDataChanged = Notification(name: NotificationName.keypadDataChanged)
|
||||
}
|
||||
enum NumericKeypadType: String {
|
||||
case BTC = "BTC"
|
||||
case SATS = "sats"
|
||||
}
|
||||
|
||||
@IBOutlet weak var periodButton: WKInterfaceButton!
|
||||
|
||||
override func awake(withContext context: Any?) {
|
||||
super.awake(withContext: context)
|
||||
if let context = context as? SpecifyInterfaceController.SpecificQRCodeContent {
|
||||
amount = context.amountStringArray
|
||||
keyPadType = context.bitcoinUnit
|
||||
}
|
||||
periodButton.setEnabled(keyPadType == .SATS)
|
||||
}
|
||||
|
||||
override func willActivate() {
|
||||
// This method is called when watch view controller is about to be visible to user
|
||||
super.willActivate()
|
||||
updateTitle()
|
||||
}
|
||||
|
||||
private func updateTitle() {
|
||||
var title = ""
|
||||
for amount in self.amount {
|
||||
let isValid = Double(amount)
|
||||
if amount == "." || isValid != nil {
|
||||
title.append(String(amount))
|
||||
}
|
||||
}
|
||||
if title.isEmpty {
|
||||
title = "0"
|
||||
}
|
||||
setTitle("< \(title) \(keyPadType)")
|
||||
NotificationCenter.default.post(name: NotificationName.keypadDataChanged, object: amount)
|
||||
}
|
||||
|
||||
private func append(value: String) {
|
||||
guard amount.filter({$0 != "."}).count <= 9 && !(amount.contains(".") && value == ".") else {
|
||||
return
|
||||
}
|
||||
switch keyPadType {
|
||||
case .SATS:
|
||||
if amount.first == "0" {
|
||||
if value == "0" {
|
||||
return
|
||||
}
|
||||
amount[0] = value
|
||||
} else {
|
||||
amount.append(value)
|
||||
}
|
||||
case .BTC:
|
||||
if amount.isEmpty {
|
||||
if (value == "0") {
|
||||
amount.append("0")
|
||||
} else if value == "." && !amount.contains(".") {
|
||||
amount.append("0")
|
||||
amount.append(".")
|
||||
} else {
|
||||
amount.append(value)
|
||||
}
|
||||
} else if let first = amount.first, first == "0" {
|
||||
if amount.count > 1, amount[1] != "." {
|
||||
amount.insert(".", at: 1)
|
||||
} else if amount.count == 1, amount.first == "0" && value != "." {
|
||||
amount.append(".")
|
||||
amount.append(value)
|
||||
} else {
|
||||
amount.append(value)
|
||||
}
|
||||
} else {
|
||||
amount.append(value)
|
||||
}
|
||||
}
|
||||
updateTitle()
|
||||
}
|
||||
|
||||
@IBAction func keypadNumberOneTapped() {
|
||||
append(value: "1")
|
||||
}
|
||||
|
||||
@IBAction func keypadNumberTwoTapped() {
|
||||
append(value: "2")
|
||||
}
|
||||
|
||||
@IBAction func keypadNumberThreeTapped() {
|
||||
append(value: "3")
|
||||
}
|
||||
|
||||
@IBAction func keypadNumberFourTapped() {
|
||||
append(value: "4")
|
||||
}
|
||||
|
||||
@IBAction func keypadNumberFiveTapped() {
|
||||
append(value: "5")
|
||||
}
|
||||
|
||||
@IBAction func keypadNumberSixTapped() {
|
||||
append(value: "6")
|
||||
}
|
||||
|
||||
@IBAction func keypadNumberSevenTapped() {
|
||||
append(value: "7")
|
||||
}
|
||||
|
||||
@IBAction func keypadNumberEightTapped() {
|
||||
append(value: "8")
|
||||
}
|
||||
|
||||
@IBAction func keypadNumberNineTapped() {
|
||||
append(value: "9")
|
||||
}
|
||||
|
||||
@IBAction func keypadNumberZeroTapped() {
|
||||
append(value: "0")
|
||||
}
|
||||
|
||||
@IBAction func keypadNumberDotTapped() {
|
||||
guard !amount.contains("."), keyPadType == .BTC else { return }
|
||||
append(value: ".")
|
||||
}
|
||||
|
||||
@IBAction func keypadNumberRemoveTapped() {
|
||||
guard !amount.isEmpty else {
|
||||
setTitle("< 0 \(keyPadType)")
|
||||
return
|
||||
}
|
||||
amount.removeLast()
|
||||
updateTitle()
|
||||
}
|
||||
|
||||
}
|
39
ios/BlueWalletWatch Extension/Objects/Transaction.swift
Normal file
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Wallet.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/13/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Transaction: NSObject, NSCoding {
|
||||
static let identifier: String = "Transaction"
|
||||
|
||||
let time: String
|
||||
let memo: String
|
||||
let amount: String
|
||||
let type: String
|
||||
|
||||
init(time: String, memo: String, type: String, amount: String) {
|
||||
self.time = time
|
||||
self.memo = memo
|
||||
self.type = type
|
||||
self.amount = amount
|
||||
}
|
||||
|
||||
func encode(with aCoder: NSCoder) {
|
||||
aCoder.encode(time, forKey: "time")
|
||||
aCoder.encode(memo, forKey: "memo")
|
||||
aCoder.encode(type, forKey: "type")
|
||||
aCoder.encode(amount, forKey: "amount")
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
time = aDecoder.decodeObject(forKey: "time") as! String
|
||||
memo = aDecoder.decodeObject(forKey: "memo") as! String
|
||||
amount = aDecoder.decodeObject(forKey: "amount") as! String
|
||||
type = aDecoder.decodeObject(forKey: "type") as! String
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// TransactionTableRow.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/10/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
import WatchKit
|
||||
|
||||
class TransactionTableRow: NSObject {
|
||||
|
||||
@IBOutlet private weak var transactionAmountLabel: WKInterfaceLabel!
|
||||
@IBOutlet private weak var transactionMemoLabel: WKInterfaceLabel!
|
||||
@IBOutlet private weak var transactionTimeLabel: WKInterfaceLabel!
|
||||
@IBOutlet private weak var transactionTypeImage: WKInterfaceImage!
|
||||
|
||||
static let identifier: String = "TransactionTableRow"
|
||||
|
||||
var amount: String = "" {
|
||||
willSet {
|
||||
transactionAmountLabel.setText(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
var memo: String = "" {
|
||||
willSet {
|
||||
transactionMemoLabel.setText(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
var time: String = "" {
|
||||
willSet {
|
||||
transactionTimeLabel.setText(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
var type: String = "" {
|
||||
willSet {
|
||||
if (newValue == "pendingConfirmation") {
|
||||
transactionTypeImage.setImage(UIImage(named: "pendingConfirmation"))
|
||||
} else if (newValue == "received") {
|
||||
transactionTypeImage.setImage(UIImage(named: "receivedArrow"))
|
||||
} else if (newValue == "sent") {
|
||||
transactionTypeImage.setImage(UIImage(named: "sentArrow"))
|
||||
} else {
|
||||
transactionTypeImage.setImage(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
51
ios/BlueWalletWatch Extension/Objects/Wallet.swift
Normal file
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// Wallet.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/13/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Wallet: NSObject, NSCoding {
|
||||
static let identifier: String = "Wallet"
|
||||
|
||||
var identifier: Int?
|
||||
let label: String
|
||||
let balance: String
|
||||
let type: String
|
||||
let preferredBalanceUnit: String
|
||||
let receiveAddress: String
|
||||
let transactions: [Transaction]
|
||||
|
||||
init(label: String, balance: String, type: String, preferredBalanceUnit: String, receiveAddress: String, transactions: [Transaction], identifier: Int) {
|
||||
self.label = label
|
||||
self.balance = balance
|
||||
self.type = type
|
||||
self.preferredBalanceUnit = preferredBalanceUnit
|
||||
self.receiveAddress = receiveAddress
|
||||
self.transactions = transactions
|
||||
self.identifier = identifier
|
||||
}
|
||||
|
||||
func encode(with aCoder: NSCoder) {
|
||||
aCoder.encode(label, forKey: "label")
|
||||
aCoder.encode(balance, forKey: "balance")
|
||||
aCoder.encode(type, forKey: "type")
|
||||
aCoder.encode(receiveAddress, forKey: "receiveAddress")
|
||||
aCoder.encode(preferredBalanceUnit, forKey: "preferredBalanceUnit")
|
||||
aCoder.encode(transactions, forKey: "transactions")
|
||||
aCoder.encode(identifier, forKey: "identifier")
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
label = aDecoder.decodeObject(forKey: "label") as! String
|
||||
balance = aDecoder.decodeObject(forKey: "balance") as! String
|
||||
type = aDecoder.decodeObject(forKey: "type") as! String
|
||||
preferredBalanceUnit = aDecoder.decodeObject(forKey: "preferredBalanceUnit") as! String
|
||||
receiveAddress = aDecoder.decodeObject(forKey: "receiveAddress") as! String
|
||||
transactions = aDecoder.decodeObject(forKey: "transactions") as? [Transaction] ?? [Transaction]()
|
||||
}
|
||||
|
||||
}
|
32
ios/BlueWalletWatch Extension/Objects/WalletGradient.swift
Normal file
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// WalletGradient.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/23/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum WalletGradient: String {
|
||||
case SegwitHD = "HDsegwitP2SH"
|
||||
case Segwit = "segwitP2SH"
|
||||
case LightningCustodial = "lightningCustodianWallet"
|
||||
case ACINQStrike = "LightningACINQ"
|
||||
case WatchOnly = "watchOnly"
|
||||
|
||||
var imageString: String{
|
||||
switch self {
|
||||
case .Segwit:
|
||||
return "wallet"
|
||||
case .ACINQStrike:
|
||||
return "walletACINQ"
|
||||
case .SegwitHD:
|
||||
return "walletHD"
|
||||
case .WatchOnly:
|
||||
return "walletWatchOnly"
|
||||
case .LightningCustodial:
|
||||
return "walletLightningCustodial"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// WalletInformation.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/10/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
import WatchKit
|
||||
|
||||
class WalletInformation: NSObject {
|
||||
|
||||
@IBOutlet private weak var walletBalanceLabel: WKInterfaceLabel!
|
||||
@IBOutlet private weak var walletNameLabel: WKInterfaceLabel!
|
||||
@IBOutlet private weak var walletGroup: WKInterfaceGroup!
|
||||
static let identifier: String = "WalletInformation"
|
||||
|
||||
var name: String = "" {
|
||||
willSet {
|
||||
walletNameLabel.setText(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
var balance: String = "" {
|
||||
willSet {
|
||||
walletBalanceLabel.setText(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
var type: WalletGradient = .SegwitHD {
|
||||
willSet {
|
||||
walletGroup.setBackgroundImageNamed(newValue.imageString)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
103
ios/BlueWalletWatch Extension/Objects/WatchDataSource.swift
Normal file
|
@ -0,0 +1,103 @@
|
|||
//
|
||||
// WatchDataSource.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/20/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
import Foundation
|
||||
import WatchConnectivity
|
||||
|
||||
class WatchDataSource: NSObject, WCSessionDelegate {
|
||||
struct NotificationName {
|
||||
static let dataUpdated = Notification.Name(rawValue: "Notification.WalletDataSource.Updated")
|
||||
}
|
||||
struct Notifications {
|
||||
static let dataUpdated = Notification(name: NotificationName.dataUpdated)
|
||||
}
|
||||
|
||||
static let shared = WatchDataSource()
|
||||
var wallets: [Wallet] = [Wallet]()
|
||||
private let keychain = KeychainSwift()
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
if WCSession.isSupported() {
|
||||
print("Activating watch session")
|
||||
WCSession.default.delegate = self
|
||||
WCSession.default.activate()
|
||||
}
|
||||
}
|
||||
|
||||
func processWalletsData(walletsInfo: [String: Any]) {
|
||||
if let walletsToProcess = walletsInfo["wallets"] as? [[String: Any]] {
|
||||
wallets.removeAll();
|
||||
for (index, entry) in walletsToProcess.enumerated() {
|
||||
guard let label = entry["label"] as? String, let balance = entry["balance"] as? String, let type = entry["type"] as? String, let preferredBalanceUnit = entry["preferredBalanceUnit"] as? String, let receiveAddress = entry["receiveAddress"] as? String, let transactions = entry["transactions"] as? [[String: Any]] else {
|
||||
continue
|
||||
}
|
||||
var transactionsProcessed = [Transaction]()
|
||||
for transactionEntry in transactions {
|
||||
guard let time = transactionEntry["time"] as? String, let memo = transactionEntry["memo"] as? String, let amount = transactionEntry["amount"] as? String, let type = transactionEntry["type"] as? String else { continue }
|
||||
let transaction = Transaction(time: time, memo: memo, type: type, amount: amount)
|
||||
transactionsProcessed.append(transaction)
|
||||
}
|
||||
let wallet = Wallet(label: label, balance: balance, type: type, preferredBalanceUnit: preferredBalanceUnit, receiveAddress: receiveAddress, transactions: transactionsProcessed, identifier: index)
|
||||
wallets.append(wallet)
|
||||
}
|
||||
|
||||
if let walletsArchived = try? NSKeyedArchiver.archivedData(withRootObject: wallets, requiringSecureCoding: false) {
|
||||
keychain.set(walletsArchived, forKey: Wallet.identifier)
|
||||
}
|
||||
WatchDataSource.postDataUpdatedNotification()
|
||||
}
|
||||
}
|
||||
|
||||
static func postDataUpdatedNotification() {
|
||||
NotificationCenter.default.post(Notifications.dataUpdated)
|
||||
}
|
||||
|
||||
static func requestLightningInvoice(walletIdentifier: Int, amount: Double, description: String?, responseHandler: @escaping (_ invoice: String) -> Void) {
|
||||
guard WatchDataSource.shared.wallets.count > walletIdentifier else {
|
||||
responseHandler("")
|
||||
return
|
||||
}
|
||||
WCSession.default.sendMessage(["request": "createInvoice", "walletIndex": walletIdentifier, "amount": amount, "description": description ?? ""], replyHandler: { (reply: [String : Any]) in
|
||||
if let invoicePaymentRequest = reply["invoicePaymentRequest"] as? String, !invoicePaymentRequest.isEmpty {
|
||||
responseHandler(invoicePaymentRequest)
|
||||
} else {
|
||||
responseHandler("")
|
||||
}
|
||||
}) { (error) in
|
||||
print(error)
|
||||
responseHandler("")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
|
||||
WatchDataSource.shared.processWalletsData(walletsInfo: applicationContext)
|
||||
}
|
||||
|
||||
func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
|
||||
WatchDataSource.shared.processWalletsData(walletsInfo: applicationContext)
|
||||
}
|
||||
|
||||
func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:]) {
|
||||
// WatchDataSource.shared.processWalletsData(walletsInfo: userInfo)
|
||||
}
|
||||
|
||||
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
|
||||
if activationState == .activated {
|
||||
WCSession.default.sendMessage([:], replyHandler: nil, errorHandler: nil)
|
||||
if let existingData = keychain.getData(Wallet.identifier), let walletData = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(existingData) as? [Wallet] {
|
||||
guard let walletData = walletData, walletData != self.wallets else { return }
|
||||
wallets = walletData
|
||||
WatchDataSource.postDataUpdatedNotification()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
20
ios/BlueWalletWatch Extension/PushNotificationPayload.apns
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"aps": {
|
||||
"alert": {
|
||||
"body": "Test message",
|
||||
"title": "Optional title",
|
||||
"subtitle": "Optional subtitle"
|
||||
},
|
||||
"category": "myCategory",
|
||||
"thread-id":"5280"
|
||||
},
|
||||
|
||||
"WatchKit Simulator Actions": [
|
||||
{
|
||||
"title": "First Button",
|
||||
"identifier": "firstButtonAction"
|
||||
}
|
||||
],
|
||||
|
||||
"customKey": "Use this file to define a testing payload for your notifications. The aps dictionary specifies the category, alert text and title. The WatchKit Simulator Actions array can provide info for one or more action buttons in addition to the standard Dismiss button. Any other top level keys are custom payload. If you have multiple such JSON files in your project, you'll be able to select them when choosing to debug the notification interface of your Watch App."
|
||||
}
|
115
ios/BlueWalletWatch Extension/ReceiveInterfaceController.swift
Normal file
|
@ -0,0 +1,115 @@
|
|||
//
|
||||
// ReceiveInterfaceController.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/12/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
import WatchKit
|
||||
import Foundation
|
||||
import EFQRCode
|
||||
|
||||
class ReceiveInterfaceController: WKInterfaceController {
|
||||
|
||||
static let identifier = "ReceiveInterfaceController"
|
||||
@IBOutlet weak var imageInterface: WKInterfaceImage!
|
||||
private var wallet: Wallet?
|
||||
private var isRenderingQRCode: Bool?
|
||||
@IBOutlet weak var loadingIndicator: WKInterfaceGroup!
|
||||
|
||||
override func awake(withContext context: Any?) {
|
||||
super.awake(withContext: context)
|
||||
guard let identifier = context as? Int, WatchDataSource.shared.wallets.count > identifier else {
|
||||
pop()
|
||||
return
|
||||
}
|
||||
let wallet = WatchDataSource.shared.wallets[identifier]
|
||||
self.wallet = wallet
|
||||
NotificationCenter.default.addObserver(forName: SpecifyInterfaceController.NotificationName.createQRCode, object: nil, queue: nil) { [weak self] (notification) in
|
||||
self?.isRenderingQRCode = true
|
||||
if let wallet = self?.wallet, wallet.type == "lightningCustodianWallet", let object = notification.object as? SpecifyInterfaceController.SpecificQRCodeContent, let amount = object.amount {
|
||||
self?.imageInterface.setHidden(true)
|
||||
self?.loadingIndicator.setHidden(false)
|
||||
WatchDataSource.requestLightningInvoice(walletIdentifier: identifier, amount: amount, description: object.description, responseHandler: { (invoice) in
|
||||
DispatchQueue.main.async {
|
||||
if (!invoice.isEmpty) {
|
||||
guard let cgImage = EFQRCode.generate(
|
||||
content: "lightning:\(invoice)") else {
|
||||
return
|
||||
}
|
||||
let image = UIImage(cgImage: cgImage)
|
||||
self?.loadingIndicator.setHidden(true)
|
||||
self?.imageInterface.setHidden(false)
|
||||
self?.imageInterface.setImage(nil)
|
||||
self?.imageInterface.setImage(image)
|
||||
} else {
|
||||
self?.pop()
|
||||
self?.presentAlert(withTitle: "Error", message: "Unable to create invoice. Please, make sure your iPhone is paired and nearby.", preferredStyle: .alert, actions: [WKAlertAction(title: "OK", style: .default, handler: { [weak self] in
|
||||
self?.dismiss()
|
||||
})])
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
guard let notificationObject = notification.object as? SpecifyInterfaceController.SpecificQRCodeContent, let walletContext = self?.wallet, !walletContext.receiveAddress.isEmpty, let receiveAddress = self?.wallet?.receiveAddress else { return }
|
||||
var address = "bitcoin:\(receiveAddress)"
|
||||
|
||||
var hasAmount = false
|
||||
if let amount = notificationObject.amount {
|
||||
address.append("?amount=\(amount)&")
|
||||
hasAmount = true
|
||||
}
|
||||
if let description = notificationObject.description {
|
||||
if (!hasAmount) {
|
||||
address.append("?")
|
||||
}
|
||||
address.append("label=\(description)")
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
guard let cgImage = EFQRCode.generate(
|
||||
content: address) else {
|
||||
return
|
||||
}
|
||||
let image = UIImage(cgImage: cgImage)
|
||||
self?.imageInterface.setImage(nil)
|
||||
self?.imageInterface.setImage(image)
|
||||
self?.imageInterface.setHidden(false)
|
||||
self?.loadingIndicator.setHidden(true)
|
||||
self?.isRenderingQRCode = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
guard !wallet.receiveAddress.isEmpty, let cgImage = EFQRCode.generate(
|
||||
content: wallet.receiveAddress) else {
|
||||
return
|
||||
}
|
||||
|
||||
let image = UIImage(cgImage: cgImage)
|
||||
imageInterface.setImage(image)
|
||||
}
|
||||
|
||||
override func didAppear() {
|
||||
super.didAppear()
|
||||
if wallet?.type == "lightningCustodianWallet" {
|
||||
if isRenderingQRCode == nil {
|
||||
presentController(withName: SpecifyInterfaceController.identifier, context: wallet?.identifier)
|
||||
isRenderingQRCode = false
|
||||
} else if isRenderingQRCode == false {
|
||||
pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func didDeactivate() {
|
||||
super.didDeactivate()
|
||||
NotificationCenter.default.removeObserver(self, name: SpecifyInterfaceController.NotificationName.createQRCode, object: nil)
|
||||
}
|
||||
|
||||
@IBAction func specifyMenuItemTapped() {
|
||||
presentController(withName: SpecifyInterfaceController.identifier, context: wallet?.identifier)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
//
|
||||
// SpecifyInterfaceController.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/23/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
import WatchKit
|
||||
import Foundation
|
||||
|
||||
class SpecifyInterfaceController: WKInterfaceController {
|
||||
|
||||
static let identifier = "SpecifyInterfaceController"
|
||||
@IBOutlet weak var descriptionButton: WKInterfaceButton!
|
||||
@IBOutlet weak var amountButton: WKInterfaceButton!
|
||||
struct SpecificQRCodeContent {
|
||||
var amount: Double?
|
||||
var description: String?
|
||||
var amountStringArray: [String] = ["0"]
|
||||
var bitcoinUnit: NumericKeypadInterfaceController.NumericKeypadType = .BTC
|
||||
}
|
||||
var specifiedQRContent: SpecificQRCodeContent = SpecificQRCodeContent(amount: nil, description: nil, amountStringArray: ["0"], bitcoinUnit: .BTC)
|
||||
var wallet: Wallet?
|
||||
struct NotificationName {
|
||||
static let createQRCode = Notification.Name(rawValue: "Notification.SpecifyInterfaceController.createQRCode")
|
||||
}
|
||||
struct Notifications {
|
||||
static let createQRCode = Notification(name: NotificationName.createQRCode)
|
||||
}
|
||||
|
||||
override func awake(withContext context: Any?) {
|
||||
super.awake(withContext: context)
|
||||
guard let identifier = context as? Int, WatchDataSource.shared.wallets.count > identifier else {
|
||||
return
|
||||
}
|
||||
let wallet = WatchDataSource.shared.wallets[identifier]
|
||||
self.wallet = wallet
|
||||
self.specifiedQRContent.bitcoinUnit = wallet.type == "lightningCustodianWallet" ? .SATS : .BTC
|
||||
NotificationCenter.default.addObserver(forName: NumericKeypadInterfaceController.NotificationName.keypadDataChanged, object: nil, queue: nil) { [weak self] (notification) in
|
||||
guard let amountObject = notification.object as? [String], !amountObject.isEmpty else { return }
|
||||
if amountObject.count == 1 && (amountObject.first == "." || amountObject.first == "0") {
|
||||
return
|
||||
}
|
||||
var title = ""
|
||||
for amount in amountObject {
|
||||
let isValid = Double(amount)
|
||||
if amount == "." || isValid != nil {
|
||||
title.append(String(amount))
|
||||
}
|
||||
}
|
||||
self?.specifiedQRContent.amountStringArray = amountObject
|
||||
if let amountDouble = Double(title), let keyPadType = self?.specifiedQRContent.bitcoinUnit {
|
||||
self?.specifiedQRContent.amount = amountDouble
|
||||
self?.amountButton.setTitle("\(title) \(keyPadType)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func didDeactivate() {
|
||||
// This method is called when watch view controller is no longer visible
|
||||
super.didDeactivate()
|
||||
NotificationCenter.default.removeObserver(self, name: NumericKeypadInterfaceController.NotificationName.keypadDataChanged, object: nil)
|
||||
}
|
||||
|
||||
@IBAction func descriptionButtonTapped() {
|
||||
presentTextInputController(withSuggestions: nil, allowedInputMode: .allowEmoji) { [weak self] (result: [Any]?) in
|
||||
DispatchQueue.main.async {
|
||||
if let result = result, let text = result.first as? String {
|
||||
self?.specifiedQRContent.description = text
|
||||
self?.descriptionButton.setTitle(nil)
|
||||
self?.descriptionButton.setTitle(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func createButtonTapped() {
|
||||
NotificationCenter.default.post(name: NotificationName.createQRCode, object: specifiedQRContent)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
override func contextForSegue(withIdentifier segueIdentifier: String) -> Any? {
|
||||
if segueIdentifier == NumericKeypadInterfaceController.identifier {
|
||||
return specifiedQRContent
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// WalletDetailsInterfaceController.swift
|
||||
// BlueWalletWatch Extension
|
||||
//
|
||||
// Created by Marcos Rodriguez on 3/11/19.
|
||||
// Copyright © 2019 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
import WatchKit
|
||||
import Foundation
|
||||
|
||||
|
||||
class WalletDetailsInterfaceController: WKInterfaceController {
|
||||
|
||||
var wallet: Wallet?
|
||||
static let identifier = "WalletDetailsInterfaceController"
|
||||
@IBOutlet weak var walletBasicsGroup: WKInterfaceGroup!
|
||||
@IBOutlet weak var walletBalanceLabel: WKInterfaceLabel!
|
||||
@IBOutlet weak var walletNameLabel: WKInterfaceLabel!
|
||||
@IBOutlet weak var receiveButton: WKInterfaceButton!
|
||||
@IBOutlet weak var noTransactionsLabel: WKInterfaceLabel!
|
||||
@IBOutlet weak var transactionsTable: WKInterfaceTable!
|
||||
|
||||
override func awake(withContext context: Any?) {
|
||||
super.awake(withContext: context)
|
||||
guard let identifier = context as? Int else {
|
||||
pop()
|
||||
return
|
||||
}
|
||||
let wallet = WatchDataSource.shared.wallets[identifier]
|
||||
self.wallet = wallet
|
||||
walletBalanceLabel.setText(wallet.balance)
|
||||
walletNameLabel.setText(wallet.label)
|
||||
walletBasicsGroup.setBackgroundImageNamed(WalletGradient(rawValue: wallet.type)?.imageString)
|
||||
|
||||
processWalletsTable()
|
||||
}
|
||||
|
||||
override func willActivate() {
|
||||
super.willActivate()
|
||||
transactionsTable.setHidden(wallet?.transactions.isEmpty ?? true)
|
||||
noTransactionsLabel.setHidden(!(wallet?.transactions.isEmpty ?? false))
|
||||
}
|
||||
|
||||
@IBAction func receiveMenuItemTapped() {
|
||||
presentController(withName: ReceiveInterfaceController.identifier, context: wallet)
|
||||
}
|
||||
|
||||
@objc private func processWalletsTable() {
|
||||
transactionsTable.setNumberOfRows(wallet?.transactions.count ?? 0, withRowType: TransactionTableRow.identifier)
|
||||
|
||||
for index in 0..<transactionsTable.numberOfRows {
|
||||
guard let controller = transactionsTable.rowController(at: index) as? TransactionTableRow, let transaction = wallet?.transactions[index] else { continue }
|
||||
|
||||
controller.amount = transaction.amount
|
||||
controller.type = transaction.type
|
||||
controller.memo = transaction.memo
|
||||
controller.time = transaction.time
|
||||
}
|
||||
transactionsTable.setHidden(wallet?.transactions.isEmpty ?? true)
|
||||
noTransactionsLabel.setHidden(!(wallet?.transactions.isEmpty ?? false))
|
||||
}
|
||||
|
||||
override func contextForSegue(withIdentifier segueIdentifier: String) -> Any? {
|
||||
return wallet?.identifier
|
||||
}
|
||||
|
||||
}
|
BIN
ios/BlueWalletWatch/Assets.xcassets/AppIcon.appiconset/1024.png
Normal file
After Width: | Height: | Size: 193 KiB |
BIN
ios/BlueWalletWatch/Assets.xcassets/AppIcon.appiconset/58.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
ios/BlueWalletWatch/Assets.xcassets/AppIcon.appiconset/87.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,92 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "24x24",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-48.png",
|
||||
"scale" : "2x",
|
||||
"role" : "notificationCenter",
|
||||
"subtype" : "38mm"
|
||||
},
|
||||
{
|
||||
"size" : "27.5x27.5",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-55.png",
|
||||
"scale" : "2x",
|
||||
"role" : "notificationCenter",
|
||||
"subtype" : "42mm"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "watch",
|
||||
"filename" : "58.png",
|
||||
"role" : "companionSettings",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "watch",
|
||||
"filename" : "87.png",
|
||||
"role" : "companionSettings",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "watch",
|
||||
"filename" : "watch.png",
|
||||
"scale" : "2x",
|
||||
"role" : "appLauncher",
|
||||
"subtype" : "38mm"
|
||||
},
|
||||
{
|
||||
"size" : "44x44",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-88.png",
|
||||
"scale" : "2x",
|
||||
"role" : "appLauncher",
|
||||
"subtype" : "40mm"
|
||||
},
|
||||
{
|
||||
"size" : "50x50",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-173.png",
|
||||
"scale" : "2x",
|
||||
"role" : "appLauncher",
|
||||
"subtype" : "44mm"
|
||||
},
|
||||
{
|
||||
"size" : "86x86",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-172.png",
|
||||
"scale" : "2x",
|
||||
"role" : "quickLook",
|
||||
"subtype" : "38mm"
|
||||
},
|
||||
{
|
||||
"size" : "98x98",
|
||||
"idiom" : "watch",
|
||||
"filename" : "Icon-196.png",
|
||||
"scale" : "2x",
|
||||
"role" : "quickLook",
|
||||
"subtype" : "42mm"
|
||||
},
|
||||
{
|
||||
"size" : "108x108",
|
||||
"idiom" : "watch",
|
||||
"filename" : "group-copy-2@3x.png",
|
||||
"scale" : "2x",
|
||||
"role" : "quickLook",
|
||||
"subtype" : "44mm"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "watch-marketing",
|
||||
"filename" : "1024.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 5 KiB |
After Width: | Height: | Size: 9 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 9.4 KiB |
BIN
ios/BlueWalletWatch/Assets.xcassets/AppIcon.appiconset/watch.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
6
ios/BlueWalletWatch/Assets.xcassets/Contents.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
13
ios/BlueWalletWatch/Assets.xcassets/loadingIndicator.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"filename" : "group-copy-2@3x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/BlueWalletWatch/Assets.xcassets/loadingIndicator.imageset/group-copy-2@3x.png
vendored
Normal file
After Width: | Height: | Size: 14 KiB |
13
ios/BlueWalletWatch/Assets.xcassets/pendingConfirmation.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"filename" : "shape@3x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/BlueWalletWatch/Assets.xcassets/pendingConfirmation.imageset/shape@3x.png
vendored
Normal file
After Width: | Height: | Size: 692 B |
13
ios/BlueWalletWatch/Assets.xcassets/qr-code.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"filename" : "qr-code@3x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/BlueWalletWatch/Assets.xcassets/qr-code.imageset/qr-code@3x.png
vendored
Normal file
After Width: | Height: | Size: 112 KiB |
13
ios/BlueWalletWatch/Assets.xcassets/receivedArrow.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"filename" : "path-copy-3@2x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/BlueWalletWatch/Assets.xcassets/receivedArrow.imageset/path-copy-3@2x.png
vendored
Normal file
After Width: | Height: | Size: 447 B |
13
ios/BlueWalletWatch/Assets.xcassets/sentArrow.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"filename" : "path-copy@2x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/BlueWalletWatch/Assets.xcassets/sentArrow.imageset/path-copy@2x.png
vendored
Normal file
After Width: | Height: | Size: 471 B |
23
ios/BlueWalletWatch/Assets.xcassets/wallet.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mask.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mask@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mask@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/BlueWalletWatch/Assets.xcassets/wallet.imageset/mask.png
vendored
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
ios/BlueWalletWatch/Assets.xcassets/wallet.imageset/mask@2x.png
vendored
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
ios/BlueWalletWatch/Assets.xcassets/wallet.imageset/mask@3x.png
vendored
Normal file
After Width: | Height: | Size: 25 KiB |
23
ios/BlueWalletWatch/Assets.xcassets/walletACINQ.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mask.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mask@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mask@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/BlueWalletWatch/Assets.xcassets/walletACINQ.imageset/mask.png
vendored
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
ios/BlueWalletWatch/Assets.xcassets/walletACINQ.imageset/mask@2x.png
vendored
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
ios/BlueWalletWatch/Assets.xcassets/walletACINQ.imageset/mask@3x.png
vendored
Normal file
After Width: | Height: | Size: 25 KiB |
13
ios/BlueWalletWatch/Assets.xcassets/walletHD.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"filename" : "mask@3x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/BlueWalletWatch/Assets.xcassets/walletHD.imageset/mask@3x.png
vendored
Normal file
After Width: | Height: | Size: 25 KiB |
13
ios/BlueWalletWatch/Assets.xcassets/walletLightningCustodial.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"filename" : "mask@3x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/BlueWalletWatch/Assets.xcassets/walletLightningCustodial.imageset/mask@3x.png
vendored
Normal file
After Width: | Height: | Size: 26 KiB |
23
ios/BlueWalletWatch/Assets.xcassets/walletWatchOnly.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mask.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mask@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mask@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/BlueWalletWatch/Assets.xcassets/walletWatchOnly.imageset/mask.png
vendored
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
ios/BlueWalletWatch/Assets.xcassets/walletWatchOnly.imageset/mask@2x.png
vendored
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
ios/BlueWalletWatch/Assets.xcassets/walletWatchOnly.imageset/mask@3x.png
vendored
Normal file
After Width: | Height: | Size: 24 KiB |
339
ios/BlueWalletWatch/Base.lproj/Interface.storyboard
Normal file
|
@ -0,0 +1,339 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="14490.70" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="AgC-eL-Hgc">
|
||||
<device id="watch44" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="watchOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="14490.21"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--BlueWallet-->
|
||||
<scene sceneID="aou-V4-d1y">
|
||||
<objects>
|
||||
<controller title="BlueWallet" fullBounds="YES" id="AgC-eL-Hgc" customClass="InterfaceController" customModule="BlueWalletWatch" customModuleProvider="target">
|
||||
<items>
|
||||
<table alignment="left" id="jUH-JS-ccp">
|
||||
<items>
|
||||
<tableRow identifier="WalletInformation" id="Rdv-UZ-gaS" customClass="WalletInformation" customModule="BlueWalletWatch_Extension">
|
||||
<group key="rootItem" width="1" height="66.5" alignment="left" backgroundImage="walletHD" radius="8" id="H28-wi-Sks" customClass="WalletInformation" customModule="BlueWalletWatch_Extension">
|
||||
<items>
|
||||
<label width="6" alignment="left" id="RJV-QC-scb"/>
|
||||
<group width="1" alignment="center" verticalAlignment="center" layout="vertical" id="UrU-xX-jYW">
|
||||
<items>
|
||||
<label width="1" alignment="left" text="Balance" minimumScaleFactor="0.5" id="QYx-3e-6zf">
|
||||
<fontDescription key="font" style="UICTFontTextStyleHeadline"/>
|
||||
</label>
|
||||
<label alignment="left" text="Wallet" id="qpj-I1-cWt"/>
|
||||
</items>
|
||||
</group>
|
||||
</items>
|
||||
</group>
|
||||
<connections>
|
||||
<outlet property="walletBalanceLabel" destination="QYx-3e-6zf" id="cfa-2U-FBQ"/>
|
||||
<outlet property="walletGroup" destination="H28-wi-Sks" id="ydq-d4-4eb"/>
|
||||
<outlet property="walletNameLabel" destination="qpj-I1-cWt" id="dd9-XB-XMc"/>
|
||||
<segue destination="XWa-4i-Abg" kind="push" identifier="WalletDetailsInterfaceController" id="Qts-pn-15q"/>
|
||||
</connections>
|
||||
</tableRow>
|
||||
</items>
|
||||
</table>
|
||||
<group width="1" alignment="left" verticalAlignment="center" layout="vertical" id="1Db-mZ-yxl">
|
||||
<items>
|
||||
<imageView width="60" height="60" alignment="center" image="loadingIndicator" contentMode="scaleAspectFit" id="dLA-pP-GUU"/>
|
||||
<label alignment="center" text="Loading wallets..." id="hCG-Eg-bck"/>
|
||||
</items>
|
||||
</group>
|
||||
<label alignment="center" verticalAlignment="center" hidden="YES" text="No wallets available. Please, add one by opening BlueWallet on your iPhone." textAlignment="center" numberOfLines="0" id="I2I-8t-hp3"/>
|
||||
</items>
|
||||
<connections>
|
||||
<outlet property="loadingIndicatorGroup" destination="1Db-mZ-yxl" id="XPX-Y8-dv0"/>
|
||||
<outlet property="noWalletsAvailableLabel" destination="I2I-8t-hp3" id="c4O-Mg-3ps"/>
|
||||
<outlet property="walletsTable" destination="jUH-JS-ccp" id="ONe-Gg-EJn"/>
|
||||
</connections>
|
||||
</controller>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="220" y="345"/>
|
||||
</scene>
|
||||
<!--WalletDetailsInterfaceController-->
|
||||
<scene sceneID="KqX-Cy-IJm">
|
||||
<objects>
|
||||
<controller identifier="WalletDetailsInterfaceController" id="XWa-4i-Abg" customClass="WalletDetailsInterfaceController" customModule="BlueWalletWatch_Extension">
|
||||
<items>
|
||||
<group width="1" height="66.5" alignment="left" backgroundImage="walletHD" radius="8" id="275-K7-Qhe" customClass="WalletInformation" customModule="BlueWalletWatch_Extension">
|
||||
<items>
|
||||
<label width="6" alignment="left" id="QMf-Fm-1cw"/>
|
||||
<group width="1" widthAdjustment="-10" alignment="center" verticalAlignment="center" layout="vertical" id="jx2-si-OEm">
|
||||
<items>
|
||||
<label alignment="left" text="Balance" minimumScaleFactor="0.5" id="WTr-jJ-w7L">
|
||||
<fontDescription key="font" style="UICTFontTextStyleHeadline"/>
|
||||
</label>
|
||||
<label width="1" alignment="left" text="Wallet" id="PQi-JV-aYW"/>
|
||||
</items>
|
||||
</group>
|
||||
</items>
|
||||
</group>
|
||||
<button width="1" alignment="left" title="Receive" id="bPO-h8-ccD">
|
||||
<color key="titleColor" red="0.18431372549019609" green="0.37254901960784315" blue="0.70196078431372544" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" red="0.80000000000000004" green="0.8666666666666667" blue="0.97647058823529409" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<fontDescription key="font" type="system" weight="medium" pointSize="16"/>
|
||||
<connections>
|
||||
<segue destination="egq-Yw-qK5" kind="push" identifier="ReceiveInterfaceController" id="zEG-Xi-Smb"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label alignment="center" verticalAlignment="bottom" text="No Transactions" textAlignment="left" id="pi4-Bk-Jiq"/>
|
||||
<table alignment="left" id="nyQ-lX-DX0">
|
||||
<items>
|
||||
<tableRow identifier="TransactionTableRow" id="HuQ-ep-L9j" customClass="TransactionTableRow" customModule="BlueWalletWatch_Extension">
|
||||
<group key="rootItem" width="1" height="0.0" alignment="left" id="3X8-cc-rOv">
|
||||
<items>
|
||||
<button alignment="left" id="NEN-rG-rmr">
|
||||
<group key="contentGroup" width="1" alignment="left" id="NY7-0s-nLc">
|
||||
<items>
|
||||
<imageView width="23" height="16" alignment="left" verticalAlignment="center" image="pendingConfirmation" contentMode="scaleAspectFit" id="hWs-WA-db1"/>
|
||||
<group width="1" alignment="left" layout="vertical" spacing="8" id="Tes-g9-rp0">
|
||||
<items>
|
||||
<label width="1" alignment="left" text="Time" minimumScaleFactor="0.10000000000000001" id="GqE-KB-TRD">
|
||||
<fontDescription key="font" style="UICTFontTextStyleSubhead"/>
|
||||
</label>
|
||||
<label width="1" alignment="left" verticalAlignment="bottom" text="memo" numberOfLines="0" id="AJ8-p9-ID7">
|
||||
<color key="textColor" red="0.63137254901960782" green="0.63137254901960782" blue="0.63137254901960782" alpha="0.84999999999999998" colorSpace="calibratedRGB"/>
|
||||
<fontDescription key="font" style="UICTFontTextStyleSubhead"/>
|
||||
</label>
|
||||
<label width="1" alignment="left" text="Amount" textAlignment="left" minimumScaleFactor="0.10000000000000001" id="sAS-LI-RY7">
|
||||
<fontDescription key="font" style="UICTFontTextStyleSubhead"/>
|
||||
</label>
|
||||
</items>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<edgeInsets key="margins" left="4" right="27" top="8" bottom="8"/>
|
||||
</group>
|
||||
</items>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</group>
|
||||
</button>
|
||||
</items>
|
||||
</group>
|
||||
<connections>
|
||||
<outlet property="transactionAmountLabel" destination="sAS-LI-RY7" id="TkE-JU-sRF"/>
|
||||
<outlet property="transactionMemoLabel" destination="AJ8-p9-ID7" id="9I4-VO-d0H"/>
|
||||
<outlet property="transactionTimeLabel" destination="GqE-KB-TRD" id="idk-sO-obD"/>
|
||||
<outlet property="transactionTypeImage" destination="hWs-WA-db1" id="BF8-T8-T5U"/>
|
||||
</connections>
|
||||
</tableRow>
|
||||
</items>
|
||||
</table>
|
||||
</items>
|
||||
<connections>
|
||||
<outlet property="noTransactionsLabel" destination="pi4-Bk-Jiq" id="zft-Hw-KuZ"/>
|
||||
<outlet property="receiveButton" destination="bPO-h8-ccD" id="xBq-42-9qP"/>
|
||||
<outlet property="transactionsTable" destination="nyQ-lX-DX0" id="N1x-px-s08"/>
|
||||
<outlet property="walletBalanceLabel" destination="WTr-jJ-w7L" id="kiU-ZS-2dh"/>
|
||||
<outlet property="walletBasicsGroup" destination="275-K7-Qhe" id="nvB-rn-8Xn"/>
|
||||
<outlet property="walletNameLabel" destination="PQi-JV-aYW" id="dfi-Ai-rOe"/>
|
||||
</connections>
|
||||
</controller>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="467.86956521739125" y="344.55357142857144"/>
|
||||
</scene>
|
||||
<!--Static Notification Interface Controller-->
|
||||
<scene sceneID="AEw-b0-oYE">
|
||||
<objects>
|
||||
<notificationController id="YCC-NB-fut">
|
||||
<items>
|
||||
<label alignment="left" text="Alert Label" numberOfLines="0" id="IdU-wH-bcW"/>
|
||||
</items>
|
||||
<notificationCategory key="notificationCategory" identifier="myCategory" id="JfB-70-Muf"/>
|
||||
<connections>
|
||||
<outlet property="notificationAlertLabel" destination="IdU-wH-bcW" id="JKC-fr-R95"/>
|
||||
<segue destination="4sK-HA-Art" kind="relationship" relationship="dynamicNotificationInterface" id="kXh-Jw-8B1"/>
|
||||
<segue destination="eXb-UN-Cd0" kind="relationship" relationship="dynamicInteractiveNotificationInterface" id="mpB-YA-K8N"/>
|
||||
</connections>
|
||||
</notificationController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="220" y="643"/>
|
||||
</scene>
|
||||
<!--Notification Controller-->
|
||||
<scene sceneID="ZPc-GJ-vnh">
|
||||
<objects>
|
||||
<controller id="4sK-HA-Art" customClass="NotificationController" customModule="BlueWalletWatch" customModuleProvider="target"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="468" y="643"/>
|
||||
</scene>
|
||||
<!--ReceiveInterfaceController-->
|
||||
<scene sceneID="tQ7-Qr-5i4">
|
||||
<objects>
|
||||
<controller identifier="ReceiveInterfaceController" fullBounds="YES" fullScreen="YES" id="egq-Yw-qK5" customClass="ReceiveInterfaceController" customModule="BlueWalletWatch_Extension">
|
||||
<items>
|
||||
<imageView height="1" alignment="left" id="Dnb-sM-wdN"/>
|
||||
<group width="1" alignment="center" verticalAlignment="center" hidden="YES" layout="vertical" id="0If-FP-smM">
|
||||
<items>
|
||||
<imageView width="60" height="60" alignment="center" image="loadingIndicator" contentMode="scaleAspectFit" id="nQb-s6-ySB"/>
|
||||
<label alignment="center" text="Creating Invoice..." id="n5f-iL-ib7"/>
|
||||
</items>
|
||||
</group>
|
||||
</items>
|
||||
<menu key="menu" id="GDw-hN-TVp">
|
||||
<items>
|
||||
<menuItem title="Customize" icon="more" id="RHB-IJ-Utd">
|
||||
<connections>
|
||||
<action selector="specifyMenuItemTapped" destination="egq-Yw-qK5" id="KMQ-wI-vdE"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<edgeInsets key="margins" left="4" right="4" top="4" bottom="4"/>
|
||||
<connections>
|
||||
<outlet property="imageInterface" destination="Dnb-sM-wdN" id="z1e-zC-anB"/>
|
||||
<outlet property="loadingIndicator" destination="0If-FP-smM" id="Wtf-mm-8Ke"/>
|
||||
</connections>
|
||||
</controller>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="716" y="345"/>
|
||||
</scene>
|
||||
<!--SpecifyInterfaceController-->
|
||||
<scene sceneID="erR-Ld-VGW">
|
||||
<objects>
|
||||
<controller identifier="SpecifyInterfaceController" id="aUg-UP-Vh5" customClass="SpecifyInterfaceController" customModule="BlueWalletWatch_Extension">
|
||||
<items>
|
||||
<button width="1" alignment="left" title="Description" id="fcI-6Z-moQ">
|
||||
<connections>
|
||||
<action selector="descriptionButtonTapped" destination="aUg-UP-Vh5" id="ZT5-rL-QZq"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button width="1" alignment="left" title="Amount" id="0Hm-hv-Yi3">
|
||||
<connections>
|
||||
<segue destination="2PN-Fb-8j5" kind="modal" identifier="NumericKeypadInterfaceController" id="LlG-6l-ghO"/>
|
||||
</connections>
|
||||
</button>
|
||||
<separator alignment="left" alpha="0.0" id="i7u-PI-g7Q">
|
||||
<color key="color" red="0.63137254899999995" green="0.63137254899999995" blue="0.63137254899999995" alpha="0.84999999999999998" colorSpace="calibratedRGB"/>
|
||||
</separator>
|
||||
<button width="1" alignment="left" verticalAlignment="bottom" title="Create" id="6eh-lx-UEe">
|
||||
<color key="titleColor" red="0.1843137255" green="0.37254901959999998" blue="0.70196078429999997" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" red="0.80000000000000004" green="0.86666666670000003" blue="0.97647058819999999" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<fontDescription key="font" type="system" weight="medium" pointSize="16"/>
|
||||
<connections>
|
||||
<action selector="createButtonTapped" destination="aUg-UP-Vh5" id="dnh-3i-jIE"/>
|
||||
</connections>
|
||||
</button>
|
||||
</items>
|
||||
<connections>
|
||||
<outlet property="amountButton" destination="0Hm-hv-Yi3" id="9DN-zh-BGB"/>
|
||||
<outlet property="descriptionButton" destination="fcI-6Z-moQ" id="a7M-ZD-Zsi"/>
|
||||
</connections>
|
||||
</controller>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="967" y="357"/>
|
||||
</scene>
|
||||
<!--NumericKeypadInterfaceController-->
|
||||
<scene sceneID="4Mp-O7-Llm">
|
||||
<objects>
|
||||
<controller identifier="NumericKeypadInterfaceController" fullBounds="YES" id="2PN-Fb-8j5" customClass="NumericKeypadInterfaceController" customModule="BlueWalletWatch_Extension">
|
||||
<items>
|
||||
<group height="0.25" alignment="left" id="kaq-2v-f7r">
|
||||
<items>
|
||||
<button width="0.33300000000000002" alignment="left" verticalAlignment="center" title="1" id="ghD-Jq-ubw">
|
||||
<fontDescription key="font" type="system" weight="heavy" pointSize="15"/>
|
||||
<connections>
|
||||
<action selector="keypadNumberOneTapped" destination="2PN-Fb-8j5" id="n6o-GR-D7i"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button width="0.33300000000000002" alignment="left" verticalAlignment="center" title="2" id="aUI-EE-NVw">
|
||||
<fontDescription key="font" type="system" weight="heavy" pointSize="15"/>
|
||||
<connections>
|
||||
<action selector="keypadNumberTwoTapped" destination="2PN-Fb-8j5" id="pfD-Db-6od"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button width="0.33300000000000002" alignment="left" verticalAlignment="center" title="3" id="TKO-lc-aYf">
|
||||
<fontDescription key="font" type="system" weight="heavy" pointSize="15"/>
|
||||
<connections>
|
||||
<action selector="keypadNumberThreeTapped" destination="2PN-Fb-8j5" id="fqm-0L-U6Z"/>
|
||||
</connections>
|
||||
</button>
|
||||
</items>
|
||||
</group>
|
||||
<group height="0.25" alignment="left" verticalAlignment="center" id="JB4-ZC-T8y">
|
||||
<items>
|
||||
<button width="0.33300000000000002" alignment="left" verticalAlignment="center" title="4" id="kH2-N1-Hbe">
|
||||
<fontDescription key="font" type="system" weight="heavy" pointSize="15"/>
|
||||
<connections>
|
||||
<action selector="keypadNumberFourTapped" destination="2PN-Fb-8j5" id="r24-dK-OUA"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button width="0.33300000000000002" alignment="left" verticalAlignment="center" title="5" id="AA6-Gq-qRe">
|
||||
<fontDescription key="font" type="system" weight="heavy" pointSize="15"/>
|
||||
<connections>
|
||||
<action selector="keypadNumberFiveTapped" destination="2PN-Fb-8j5" id="yTW-cf-ZCP"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button width="0.33300000000000002" alignment="left" verticalAlignment="center" title="6" id="Nt9-we-M9f">
|
||||
<fontDescription key="font" type="system" weight="heavy" pointSize="15"/>
|
||||
<connections>
|
||||
<action selector="keypadNumberSixTapped" destination="2PN-Fb-8j5" id="xOh-ab-nWm"/>
|
||||
</connections>
|
||||
</button>
|
||||
</items>
|
||||
</group>
|
||||
<group height="0.25" alignment="left" verticalAlignment="center" id="CT1-xK-izT">
|
||||
<items>
|
||||
<button width="0.33300000000000002" alignment="left" verticalAlignment="center" title="7" id="ohU-B0-mvg">
|
||||
<fontDescription key="font" type="system" weight="heavy" pointSize="15"/>
|
||||
<connections>
|
||||
<action selector="keypadNumberSevenTapped" destination="2PN-Fb-8j5" id="8CA-Q5-XZt"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button width="0.33300000000000002" alignment="left" verticalAlignment="center" title="8" id="3FQ-tZ-9kd">
|
||||
<fontDescription key="font" type="system" weight="heavy" pointSize="15"/>
|
||||
<connections>
|
||||
<action selector="keypadNumberEightTapped" destination="2PN-Fb-8j5" id="4h8-vi-GjT"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button width="0.33300000000000002" alignment="left" verticalAlignment="center" title="9" id="NJM-uR-nyO">
|
||||
<fontDescription key="font" type="system" weight="heavy" pointSize="15"/>
|
||||
<connections>
|
||||
<action selector="keypadNumberNineTapped" destination="2PN-Fb-8j5" id="qpZ-nf-E5y"/>
|
||||
</connections>
|
||||
</button>
|
||||
</items>
|
||||
</group>
|
||||
<group height="0.25" alignment="left" verticalAlignment="center" id="hqA-Nb-d5C">
|
||||
<items>
|
||||
<button width="0.33300000000000002" height="1" alignment="left" verticalAlignment="center" title="." id="g6Z-9t-ahQ">
|
||||
<fontDescription key="font" type="system" weight="heavy" pointSize="15"/>
|
||||
<connections>
|
||||
<action selector="keypadNumberDotTapped" destination="2PN-Fb-8j5" id="K7P-bQ-h24"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button width="0.33300000000000002" height="1" alignment="left" verticalAlignment="center" title="0" id="S1H-Id-l6g">
|
||||
<fontDescription key="font" type="system" weight="heavy" pointSize="15"/>
|
||||
<connections>
|
||||
<action selector="keypadNumberZeroTapped" destination="2PN-Fb-8j5" id="YH1-KR-oIu"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button width="0.33300000000000002" height="1" alignment="left" verticalAlignment="center" title="<" id="q8Q-tK-nzd">
|
||||
<fontDescription key="font" type="system" weight="heavy" pointSize="15"/>
|
||||
<connections>
|
||||
<action selector="keypadNumberRemoveTapped" destination="2PN-Fb-8j5" id="l7u-ZB-AyF"/>
|
||||
</connections>
|
||||
</button>
|
||||
</items>
|
||||
</group>
|
||||
</items>
|
||||
<connections>
|
||||
<outlet property="periodButton" destination="g6Z-9t-ahQ" id="ynz-0C-Fxe"/>
|
||||
</connections>
|
||||
</controller>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1197" y="357"/>
|
||||
</scene>
|
||||
<!--Notification Controller-->
|
||||
<scene sceneID="Niz-AI-uX2">
|
||||
<objects>
|
||||
<controller id="eXb-UN-Cd0" customClass="NotificationController" customModule="BlueWalletWatch" customModuleProvider="target"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="220" y="1029"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<color key="tintColor" red="0.40784313725490196" green="0.73333333333333328" blue="0.88235294117647056" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</document>
|
33
ios/BlueWalletWatch/Info.plist
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>BlueWallet</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.9.8</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>239</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
<key>WKCompanionAppBundleIdentifier</key>
|
||||
<string>io.bluewallet.bluewallet</string>
|
||||
<key>WKWatchKitApp</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
454
ios/KeychainSwiftDistrib.swift
Normal file
|
@ -0,0 +1,454 @@
|
|||
//
|
||||
// Keychain helper for iOS/Swift.
|
||||
//
|
||||
// https://github.com/evgenyneu/keychain-swift
|
||||
//
|
||||
// This file was automatically generated by combining multiple Swift source files.
|
||||
//
|
||||
|
||||
|
||||
// ----------------------------
|
||||
//
|
||||
// KeychainSwift.swift
|
||||
//
|
||||
// ----------------------------
|
||||
|
||||
import Security
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
|
||||
A collection of helper functions for saving text and data in the keychain.
|
||||
|
||||
*/
|
||||
open class KeychainSwift {
|
||||
|
||||
var lastQueryParameters: [String: Any]? // Used by the unit tests
|
||||
|
||||
/// Contains result code from the last operation. Value is noErr (0) for a successful result.
|
||||
open var lastResultCode: OSStatus = noErr
|
||||
|
||||
var keyPrefix = "" // Can be useful in test.
|
||||
|
||||
/**
|
||||
|
||||
Specify an access group that will be used to access keychain items. Access groups can be used to share keychain items between applications. When access group value is nil all application access groups are being accessed. Access group name is used by all functions: set, get, delete and clear.
|
||||
|
||||
*/
|
||||
open var accessGroup: String?
|
||||
|
||||
|
||||
/**
|
||||
|
||||
Specifies whether the items can be synchronized with other devices through iCloud. Setting this property to true will
|
||||
add the item to other devices with the `set` method and obtain synchronizable items with the `get` command. Deleting synchronizable items will remove them from all devices. In order for keychain synchronization to work the user must enable "Keychain" in iCloud settings.
|
||||
|
||||
Does not work on macOS.
|
||||
|
||||
*/
|
||||
open var synchronizable: Bool = false
|
||||
|
||||
private let readLock = NSLock()
|
||||
|
||||
/// Instantiate a KeychainSwift object
|
||||
public init() { }
|
||||
|
||||
/**
|
||||
|
||||
- parameter keyPrefix: a prefix that is added before the key in get/set methods. Note that `clear` method still clears everything from the Keychain.
|
||||
|
||||
*/
|
||||
public init(keyPrefix: String) {
|
||||
self.keyPrefix = keyPrefix
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Stores the text value in the keychain item under the given key.
|
||||
|
||||
- parameter key: Key under which the text value is stored in the keychain.
|
||||
- parameter value: Text string to be written to the keychain.
|
||||
- parameter withAccess: Value that indicates when your app needs access to the text in the keychain item. By default the .AccessibleWhenUnlocked option is used that permits the data to be accessed only while the device is unlocked by the user.
|
||||
|
||||
- returns: True if the text was successfully written to the keychain.
|
||||
|
||||
*/
|
||||
@discardableResult
|
||||
open func set(_ value: String, forKey key: String,
|
||||
withAccess access: KeychainSwiftAccessOptions? = nil) -> Bool {
|
||||
|
||||
if let value = value.data(using: String.Encoding.utf8) {
|
||||
return set(value, forKey: key, withAccess: access)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Stores the data in the keychain item under the given key.
|
||||
|
||||
- parameter key: Key under which the data is stored in the keychain.
|
||||
- parameter value: Data to be written to the keychain.
|
||||
- parameter withAccess: Value that indicates when your app needs access to the text in the keychain item. By default the .AccessibleWhenUnlocked option is used that permits the data to be accessed only while the device is unlocked by the user.
|
||||
|
||||
- returns: True if the text was successfully written to the keychain.
|
||||
|
||||
*/
|
||||
@discardableResult
|
||||
open func set(_ value: Data, forKey key: String,
|
||||
withAccess access: KeychainSwiftAccessOptions? = nil) -> Bool {
|
||||
|
||||
delete(key) // Delete any existing key before saving it
|
||||
|
||||
let accessible = access?.value ?? KeychainSwiftAccessOptions.defaultOption.value
|
||||
|
||||
let prefixedKey = keyWithPrefix(key)
|
||||
|
||||
var query: [String : Any] = [
|
||||
KeychainSwiftConstants.klass : kSecClassGenericPassword,
|
||||
KeychainSwiftConstants.attrAccount : prefixedKey,
|
||||
KeychainSwiftConstants.valueData : value,
|
||||
KeychainSwiftConstants.accessible : accessible
|
||||
]
|
||||
|
||||
query = addAccessGroupWhenPresent(query)
|
||||
query = addSynchronizableIfRequired(query, addingItems: true)
|
||||
lastQueryParameters = query
|
||||
|
||||
lastResultCode = SecItemAdd(query as CFDictionary, nil)
|
||||
|
||||
return lastResultCode == noErr
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Stores the boolean value in the keychain item under the given key.
|
||||
|
||||
- parameter key: Key under which the value is stored in the keychain.
|
||||
- parameter value: Boolean to be written to the keychain.
|
||||
- parameter withAccess: Value that indicates when your app needs access to the value in the keychain item. By default the .AccessibleWhenUnlocked option is used that permits the data to be accessed only while the device is unlocked by the user.
|
||||
|
||||
- returns: True if the value was successfully written to the keychain.
|
||||
|
||||
*/
|
||||
@discardableResult
|
||||
open func set(_ value: Bool, forKey key: String,
|
||||
withAccess access: KeychainSwiftAccessOptions? = nil) -> Bool {
|
||||
|
||||
let bytes: [UInt8] = value ? [1] : [0]
|
||||
let data = Data(bytes)
|
||||
|
||||
return set(data, forKey: key, withAccess: access)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Retrieves the text value from the keychain that corresponds to the given key.
|
||||
|
||||
- parameter key: The key that is used to read the keychain item.
|
||||
- returns: The text value from the keychain. Returns nil if unable to read the item.
|
||||
|
||||
*/
|
||||
open func get(_ key: String) -> String? {
|
||||
if let data = getData(key) {
|
||||
|
||||
if let currentString = String(data: data, encoding: .utf8) {
|
||||
return currentString
|
||||
}
|
||||
|
||||
lastResultCode = -67853 // errSecInvalidEncoding
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Retrieves the data from the keychain that corresponds to the given key.
|
||||
|
||||
- parameter key: The key that is used to read the keychain item.
|
||||
- returns: The text value from the keychain. Returns nil if unable to read the item.
|
||||
|
||||
*/
|
||||
open func getData(_ key: String) -> Data? {
|
||||
// The lock prevents the code to be run simlultaneously
|
||||
// from multiple threads which may result in crashing
|
||||
readLock.lock()
|
||||
defer { readLock.unlock() }
|
||||
|
||||
let prefixedKey = keyWithPrefix(key)
|
||||
|
||||
var query: [String: Any] = [
|
||||
KeychainSwiftConstants.klass : kSecClassGenericPassword,
|
||||
KeychainSwiftConstants.attrAccount : prefixedKey,
|
||||
KeychainSwiftConstants.returnData : kCFBooleanTrue!,
|
||||
KeychainSwiftConstants.matchLimit : kSecMatchLimitOne
|
||||
]
|
||||
|
||||
query = addAccessGroupWhenPresent(query)
|
||||
query = addSynchronizableIfRequired(query, addingItems: false)
|
||||
lastQueryParameters = query
|
||||
|
||||
var result: AnyObject?
|
||||
|
||||
lastResultCode = withUnsafeMutablePointer(to: &result) {
|
||||
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
|
||||
}
|
||||
|
||||
if lastResultCode == noErr { return result as? Data }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Retrieves the boolean value from the keychain that corresponds to the given key.
|
||||
|
||||
- parameter key: The key that is used to read the keychain item.
|
||||
- returns: The boolean value from the keychain. Returns nil if unable to read the item.
|
||||
|
||||
*/
|
||||
open func getBool(_ key: String) -> Bool? {
|
||||
guard let data = getData(key) else { return nil }
|
||||
guard let firstBit = data.first else { return nil }
|
||||
return firstBit == 1
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Deletes the single keychain item specified by the key.
|
||||
|
||||
- parameter key: The key that is used to delete the keychain item.
|
||||
- returns: True if the item was successfully deleted.
|
||||
|
||||
*/
|
||||
@discardableResult
|
||||
open func delete(_ key: String) -> Bool {
|
||||
let prefixedKey = keyWithPrefix(key)
|
||||
|
||||
var query: [String: Any] = [
|
||||
KeychainSwiftConstants.klass : kSecClassGenericPassword,
|
||||
KeychainSwiftConstants.attrAccount : prefixedKey
|
||||
]
|
||||
|
||||
query = addAccessGroupWhenPresent(query)
|
||||
query = addSynchronizableIfRequired(query, addingItems: false)
|
||||
lastQueryParameters = query
|
||||
|
||||
lastResultCode = SecItemDelete(query as CFDictionary)
|
||||
|
||||
return lastResultCode == noErr
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Deletes all Keychain items used by the app. Note that this method deletes all items regardless of the prefix settings used for initializing the class.
|
||||
|
||||
- returns: True if the keychain items were successfully deleted.
|
||||
|
||||
*/
|
||||
@discardableResult
|
||||
open func clear() -> Bool {
|
||||
var query: [String: Any] = [ kSecClass as String : kSecClassGenericPassword ]
|
||||
query = addAccessGroupWhenPresent(query)
|
||||
query = addSynchronizableIfRequired(query, addingItems: false)
|
||||
lastQueryParameters = query
|
||||
|
||||
lastResultCode = SecItemDelete(query as CFDictionary)
|
||||
|
||||
return lastResultCode == noErr
|
||||
}
|
||||
|
||||
/// Returns the key with currently set prefix.
|
||||
func keyWithPrefix(_ key: String) -> String {
|
||||
return "\(keyPrefix)\(key)"
|
||||
}
|
||||
|
||||
func addAccessGroupWhenPresent(_ items: [String: Any]) -> [String: Any] {
|
||||
guard let accessGroup = accessGroup else { return items }
|
||||
|
||||
var result: [String: Any] = items
|
||||
result[KeychainSwiftConstants.accessGroup] = accessGroup
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Adds kSecAttrSynchronizable: kSecAttrSynchronizableAny` item to the dictionary when the `synchronizable` property is true.
|
||||
|
||||
- parameter items: The dictionary where the kSecAttrSynchronizable items will be added when requested.
|
||||
- parameter addingItems: Use `true` when the dictionary will be used with `SecItemAdd` method (adding a keychain item). For getting and deleting items, use `false`.
|
||||
|
||||
- returns: the dictionary with kSecAttrSynchronizable item added if it was requested. Otherwise, it returns the original dictionary.
|
||||
|
||||
*/
|
||||
func addSynchronizableIfRequired(_ items: [String: Any], addingItems: Bool) -> [String: Any] {
|
||||
if !synchronizable { return items }
|
||||
var result: [String: Any] = items
|
||||
result[KeychainSwiftConstants.attrSynchronizable] = addingItems == true ? true : kSecAttrSynchronizableAny
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------
|
||||
//
|
||||
// TegKeychainConstants.swift
|
||||
//
|
||||
// ----------------------------
|
||||
|
||||
import Foundation
|
||||
import Security
|
||||
|
||||
/// Constants used by the library
|
||||
public struct KeychainSwiftConstants {
|
||||
/// Specifies a Keychain access group. Used for sharing Keychain items between apps.
|
||||
public static var accessGroup: String { return toString(kSecAttrAccessGroup) }
|
||||
|
||||
/**
|
||||
|
||||
A value that indicates when your app needs access to the data in a keychain item. The default value is AccessibleWhenUnlocked. For a list of possible values, see KeychainSwiftAccessOptions.
|
||||
|
||||
*/
|
||||
public static var accessible: String { return toString(kSecAttrAccessible) }
|
||||
|
||||
/// Used for specifying a String key when setting/getting a Keychain value.
|
||||
public static var attrAccount: String { return toString(kSecAttrAccount) }
|
||||
|
||||
/// Used for specifying synchronization of keychain items between devices.
|
||||
public static var attrSynchronizable: String { return toString(kSecAttrSynchronizable) }
|
||||
|
||||
/// An item class key used to construct a Keychain search dictionary.
|
||||
public static var klass: String { return toString(kSecClass) }
|
||||
|
||||
/// Specifies the number of values returned from the keychain. The library only supports single values.
|
||||
public static var matchLimit: String { return toString(kSecMatchLimit) }
|
||||
|
||||
/// A return data type used to get the data from the Keychain.
|
||||
public static var returnData: String { return toString(kSecReturnData) }
|
||||
|
||||
/// Used for specifying a value when setting a Keychain value.
|
||||
public static var valueData: String { return toString(kSecValueData) }
|
||||
|
||||
static func toString(_ value: CFString) -> String {
|
||||
return value as String
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------
|
||||
//
|
||||
// KeychainSwiftAccessOptions.swift
|
||||
//
|
||||
// ----------------------------
|
||||
|
||||
import Security
|
||||
|
||||
/**
|
||||
|
||||
These options are used to determine when a keychain item should be readable. The default value is AccessibleWhenUnlocked.
|
||||
|
||||
*/
|
||||
public enum KeychainSwiftAccessOptions {
|
||||
|
||||
/**
|
||||
|
||||
The data in the keychain item can be accessed only while the device is unlocked by the user.
|
||||
|
||||
This is recommended for items that need to be accessible only while the application is in the foreground. Items with this attribute migrate to a new device when using encrypted backups.
|
||||
|
||||
This is the default value for keychain items added without explicitly setting an accessibility constant.
|
||||
|
||||
*/
|
||||
case accessibleWhenUnlocked
|
||||
|
||||
/**
|
||||
|
||||
The data in the keychain item can be accessed only while the device is unlocked by the user.
|
||||
|
||||
This is recommended for items that need to be accessible only while the application is in the foreground. Items with this attribute do not migrate to a new device. Thus, after restoring from a backup of a different device, these items will not be present.
|
||||
|
||||
*/
|
||||
case accessibleWhenUnlockedThisDeviceOnly
|
||||
|
||||
/**
|
||||
|
||||
The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.
|
||||
|
||||
After the first unlock, the data remains accessible until the next restart. This is recommended for items that need to be accessed by background applications. Items with this attribute migrate to a new device when using encrypted backups.
|
||||
|
||||
*/
|
||||
case accessibleAfterFirstUnlock
|
||||
|
||||
/**
|
||||
|
||||
The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.
|
||||
|
||||
After the first unlock, the data remains accessible until the next restart. This is recommended for items that need to be accessed by background applications. Items with this attribute do not migrate to a new device. Thus, after restoring from a backup of a different device, these items will not be present.
|
||||
|
||||
*/
|
||||
case accessibleAfterFirstUnlockThisDeviceOnly
|
||||
|
||||
/**
|
||||
|
||||
The data in the keychain item can always be accessed regardless of whether the device is locked.
|
||||
|
||||
This is not recommended for application use. Items with this attribute migrate to a new device when using encrypted backups.
|
||||
|
||||
*/
|
||||
case accessibleAlways
|
||||
|
||||
/**
|
||||
|
||||
The data in the keychain can only be accessed when the device is unlocked. Only available if a passcode is set on the device.
|
||||
|
||||
This is recommended for items that only need to be accessible while the application is in the foreground. Items with this attribute never migrate to a new device. After a backup is restored to a new device, these items are missing. No items can be stored in this class on devices without a passcode. Disabling the device passcode causes all items in this class to be deleted.
|
||||
|
||||
*/
|
||||
case accessibleWhenPasscodeSetThisDeviceOnly
|
||||
|
||||
/**
|
||||
|
||||
The data in the keychain item can always be accessed regardless of whether the device is locked.
|
||||
|
||||
This is not recommended for application use. Items with this attribute do not migrate to a new device. Thus, after restoring from a backup of a different device, these items will not be present.
|
||||
|
||||
*/
|
||||
case accessibleAlwaysThisDeviceOnly
|
||||
|
||||
static var defaultOption: KeychainSwiftAccessOptions {
|
||||
return .accessibleWhenUnlocked
|
||||
}
|
||||
|
||||
var value: String {
|
||||
switch self {
|
||||
case .accessibleWhenUnlocked:
|
||||
return toString(kSecAttrAccessibleWhenUnlocked)
|
||||
|
||||
case .accessibleWhenUnlockedThisDeviceOnly:
|
||||
return toString(kSecAttrAccessibleWhenUnlockedThisDeviceOnly)
|
||||
|
||||
case .accessibleAfterFirstUnlock:
|
||||
return toString(kSecAttrAccessibleAfterFirstUnlock)
|
||||
|
||||
case .accessibleAfterFirstUnlockThisDeviceOnly:
|
||||
return toString(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly)
|
||||
|
||||
case .accessibleAlways:
|
||||
return toString(kSecAttrAccessibleAlways)
|
||||
|
||||
case .accessibleWhenPasscodeSetThisDeviceOnly:
|
||||
return toString(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly)
|
||||
|
||||
case .accessibleAlwaysThisDeviceOnly:
|
||||
return toString(kSecAttrAccessibleAlwaysThisDeviceOnly)
|
||||
}
|
||||
}
|
||||
|
||||
func toString(_ value: CFString) -> String {
|
||||
return KeychainSwiftConstants.toString(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
127
ios/Podfile
Normal file
|
@ -0,0 +1,127 @@
|
|||
|
||||
# Uncomment the next line to define a global platform for your project
|
||||
# platform :ios, '9.0'
|
||||
platform :ios, '10.0'
|
||||
workspace 'BlueWallet'
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
target.build_configurations.each do |config|
|
||||
puts "Setting Swift Version setting for #{target.name}..."
|
||||
config.build_settings['SWIFT_VERSION'] = '4.2'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def sharedPods
|
||||
# Explicitly include Yoga if you are using RN >= 0.42.0
|
||||
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
|
||||
|
||||
# Third party deps podspec link
|
||||
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
|
||||
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
|
||||
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
|
||||
pod 'React', :path => '../node_modules/react-native', :subspecs => [
|
||||
'Core',
|
||||
'CxxBridge', # Include this for RN >= 0.47
|
||||
'DevSupport', # Include this to enable In-App Devmenu if RN >= 0.43
|
||||
'RCTText',
|
||||
'RCTImage', # <-- Add RCTImage
|
||||
'RCTNetwork',
|
||||
'RCTActionSheet',
|
||||
'RCTLinkingIOS',
|
||||
'RCTWebSocket', # Needed for debugging
|
||||
'RCTAnimation', # Needed for FlatList and animations running on native UI thread
|
||||
# Add any other subspecs you want to use in your project
|
||||
]
|
||||
end
|
||||
|
||||
target 'BlueWallet' do
|
||||
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
|
||||
# use_frameworks!
|
||||
project 'BlueWallet.xcodeproj'
|
||||
platform :ios, '10.0'
|
||||
# Pods for BlueWallet
|
||||
# React Native requirements
|
||||
|
||||
sharedPods
|
||||
pod 'RNWatch', :path => '../node_modules/react-native-watch-connectivity'
|
||||
|
||||
pod 'react-native-webview', :path => '../node_modules/react-native-webview'
|
||||
|
||||
pod 'react-native-camera', :path => '../node_modules/react-native-camera'
|
||||
|
||||
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
|
||||
|
||||
pod 'RNGestureHandler', :path => '../node_modules/react-native-gesture-handler'
|
||||
|
||||
pod 'RNFS', :path => '../node_modules/react-native-fs'
|
||||
|
||||
pod 'react-native-google-analytics-bridge', :path => '../node_modules/react-native-google-analytics-bridge'
|
||||
|
||||
pod 'react-native-haptic-feedback', :path => '../node_modules/react-native-haptic-feedback'
|
||||
|
||||
pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'
|
||||
|
||||
pod 'RNRate', :path => '../node_modules/react-native-rate/ios'
|
||||
|
||||
pod 'react-native-image-picker', :path => '../node_modules/react-native-image-picker'
|
||||
|
||||
pod 'RNSVG', :path => '../node_modules/react-native-svg'
|
||||
|
||||
pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
|
||||
|
||||
pod 'react-native-randombytes', :path => '../node_modules/react-native-randombytes'
|
||||
|
||||
pod 'react-native-slider', :path => '../node_modules/@react-native-community/slider'
|
||||
|
||||
pod 'SentryReactNative', :path => '../node_modules/react-native-sentry'
|
||||
|
||||
pod 'ToolTipMenu', :path => '../node_modules/react-native-tooltip'
|
||||
|
||||
pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage'
|
||||
|
||||
end
|
||||
|
||||
target 'BlueWalletTests' do
|
||||
inherit! :search_paths
|
||||
# Pods for testing
|
||||
|
||||
end
|
||||
|
||||
target 'BlueWalletWatch' do
|
||||
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
|
||||
# use_frameworks!
|
||||
# Pods for BlueWalletWatch
|
||||
platform :watchos, '5.1'
|
||||
end
|
||||
|
||||
target 'BlueWalletWatch Extension' do
|
||||
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
|
||||
# use_frameworks!
|
||||
platform :watchos, '5.1'
|
||||
pod 'EFQRCode', '~> 5.0.0'
|
||||
# Pods for BlueWalletWatch Extension
|
||||
end
|
||||
|
||||
|
||||
target 'TcpSockets' do
|
||||
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
|
||||
# use_frameworks!
|
||||
project '../node_modules/react-native-tcp/ios/TcpSockets.xcodeproj'
|
||||
sharedPods
|
||||
end
|
||||
|
||||
target 'RCTQRCodeLocalImage' do
|
||||
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
|
||||
# use_frameworks!
|
||||
project '../node_modules/@remobile/react-native-qrcode-local-image/ios/RCTQRCodeLocalImage.xcodeproj'
|
||||
sharedPods
|
||||
end
|
||||
|
||||
target 'RCTPrivacySnapshot' do
|
||||
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
|
||||
# use_frameworks!
|
||||
project '../node_modules/react-native-privacy-snapshot/RCTPrivacySnapshot.xcodeproj'
|
||||
sharedPods
|
||||
end
|
232
ios/Podfile.lock
Normal file
|
@ -0,0 +1,232 @@
|
|||
PODS:
|
||||
- boost-for-react-native (1.63.0)
|
||||
- BVLinearGradient (2.5.4):
|
||||
- React
|
||||
- DoubleConversion (1.1.6)
|
||||
- EFQRCode (5.0.0):
|
||||
- swift_qrcodejs (~> 1.1.1)
|
||||
- Folly (2018.10.22.00):
|
||||
- boost-for-react-native
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- glog (0.3.5)
|
||||
- React (0.59.6):
|
||||
- React/Core (= 0.59.6)
|
||||
- react-native-camera (2.6.0):
|
||||
- React
|
||||
- react-native-camera/RCT (= 2.6.0)
|
||||
- react-native-camera/RN (= 2.6.0)
|
||||
- react-native-camera/RCT (2.6.0):
|
||||
- React
|
||||
- react-native-camera/RN (2.6.0):
|
||||
- React
|
||||
- react-native-google-analytics-bridge (7.1.0):
|
||||
- react-native-google-analytics-bridge/Core (= 7.1.0)
|
||||
- react-native-google-analytics-bridge/Core (7.1.0):
|
||||
- React
|
||||
- react-native-haptic-feedback (1.7.1):
|
||||
- React
|
||||
- react-native-image-picker (0.28.1):
|
||||
- React
|
||||
- react-native-randombytes (3.5.2):
|
||||
- React
|
||||
- react-native-slider (1.1.0):
|
||||
- React
|
||||
- react-native-webview (5.8.1):
|
||||
- React
|
||||
- React/Core (0.59.6):
|
||||
- yoga (= 0.59.6.React)
|
||||
- React/CxxBridge (0.59.6):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- React/Core
|
||||
- React/cxxreact
|
||||
- React/jsiexecutor
|
||||
- React/cxxreact (0.59.6):
|
||||
- boost-for-react-native (= 1.63.0)
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React/jsinspector
|
||||
- React/DevSupport (0.59.6):
|
||||
- React/Core
|
||||
- React/RCTWebSocket
|
||||
- React/fishhook (0.59.6)
|
||||
- React/jsi (0.59.6):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React/jsiexecutor (0.59.6):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React/cxxreact
|
||||
- React/jsi
|
||||
- React/jsinspector (0.59.6)
|
||||
- React/RCTActionSheet (0.59.6):
|
||||
- React/Core
|
||||
- React/RCTAnimation (0.59.6):
|
||||
- React/Core
|
||||
- React/RCTBlob (0.59.6):
|
||||
- React/Core
|
||||
- React/RCTImage (0.59.6):
|
||||
- React/Core
|
||||
- React/RCTNetwork
|
||||
- React/RCTLinkingIOS (0.59.6):
|
||||
- React/Core
|
||||
- React/RCTNetwork (0.59.6):
|
||||
- React/Core
|
||||
- React/RCTText (0.59.6):
|
||||
- React/Core
|
||||
- React/RCTWebSocket (0.59.6):
|
||||
- React/Core
|
||||
- React/fishhook
|
||||
- React/RCTBlob
|
||||
- RNCAsyncStorage (1.3.3):
|
||||
- React
|
||||
- RNDeviceInfo (1.6.0):
|
||||
- React
|
||||
- RNFS (2.13.3):
|
||||
- React
|
||||
- RNGestureHandler (1.2.0):
|
||||
- React
|
||||
- RNRate (1.0.1):
|
||||
- React
|
||||
- RNSVG (9.4.0):
|
||||
- React
|
||||
- RNVectorIcons (6.4.2):
|
||||
- React
|
||||
- RNWatch (0.2.0):
|
||||
- React
|
||||
- Sentry (4.1.3):
|
||||
- Sentry/Core (= 4.1.3)
|
||||
- Sentry/Core (4.1.3)
|
||||
- SentryReactNative (0.42.0):
|
||||
- React
|
||||
- Sentry (~> 4.1.3)
|
||||
- swift_qrcodejs (1.1.1)
|
||||
- ToolTipMenu (5.2.1):
|
||||
- React
|
||||
- yoga (0.59.6.React)
|
||||
|
||||
DEPENDENCIES:
|
||||
- BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
|
||||
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
||||
- EFQRCode (~> 5.0.0)
|
||||
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
||||
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||
- react-native-camera (from `../node_modules/react-native-camera`)
|
||||
- react-native-google-analytics-bridge (from `../node_modules/react-native-google-analytics-bridge`)
|
||||
- react-native-haptic-feedback (from `../node_modules/react-native-haptic-feedback`)
|
||||
- react-native-image-picker (from `../node_modules/react-native-image-picker`)
|
||||
- react-native-randombytes (from `../node_modules/react-native-randombytes`)
|
||||
- "react-native-slider (from `../node_modules/@react-native-community/slider`)"
|
||||
- react-native-webview (from `../node_modules/react-native-webview`)
|
||||
- React/Core (from `../node_modules/react-native`)
|
||||
- React/CxxBridge (from `../node_modules/react-native`)
|
||||
- React/DevSupport (from `../node_modules/react-native`)
|
||||
- React/RCTActionSheet (from `../node_modules/react-native`)
|
||||
- React/RCTAnimation (from `../node_modules/react-native`)
|
||||
- React/RCTImage (from `../node_modules/react-native`)
|
||||
- React/RCTLinkingIOS (from `../node_modules/react-native`)
|
||||
- React/RCTNetwork (from `../node_modules/react-native`)
|
||||
- React/RCTText (from `../node_modules/react-native`)
|
||||
- React/RCTWebSocket (from `../node_modules/react-native`)
|
||||
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
|
||||
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
||||
- RNFS (from `../node_modules/react-native-fs`)
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- RNRate (from `../node_modules/react-native-rate/ios`)
|
||||
- RNSVG (from `../node_modules/react-native-svg`)
|
||||
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
|
||||
- RNWatch (from `../node_modules/react-native-watch-connectivity`)
|
||||
- SentryReactNative (from `../node_modules/react-native-sentry`)
|
||||
- ToolTipMenu (from `../node_modules/react-native-tooltip`)
|
||||
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- boost-for-react-native
|
||||
- EFQRCode
|
||||
- Sentry
|
||||
- swift_qrcodejs
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
BVLinearGradient:
|
||||
:path: "../node_modules/react-native-linear-gradient"
|
||||
DoubleConversion:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
|
||||
Folly:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
|
||||
glog:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
|
||||
React:
|
||||
:path: "../node_modules/react-native"
|
||||
react-native-camera:
|
||||
:path: "../node_modules/react-native-camera"
|
||||
react-native-google-analytics-bridge:
|
||||
:path: "../node_modules/react-native-google-analytics-bridge"
|
||||
react-native-haptic-feedback:
|
||||
:path: "../node_modules/react-native-haptic-feedback"
|
||||
react-native-image-picker:
|
||||
:path: "../node_modules/react-native-image-picker"
|
||||
react-native-randombytes:
|
||||
:path: "../node_modules/react-native-randombytes"
|
||||
react-native-slider:
|
||||
:path: "../node_modules/@react-native-community/slider"
|
||||
react-native-webview:
|
||||
:path: "../node_modules/react-native-webview"
|
||||
RNCAsyncStorage:
|
||||
:path: "../node_modules/@react-native-community/async-storage"
|
||||
RNDeviceInfo:
|
||||
:path: "../node_modules/react-native-device-info"
|
||||
RNFS:
|
||||
:path: "../node_modules/react-native-fs"
|
||||
RNGestureHandler:
|
||||
:path: "../node_modules/react-native-gesture-handler"
|
||||
RNRate:
|
||||
:path: "../node_modules/react-native-rate/ios"
|
||||
RNSVG:
|
||||
:path: "../node_modules/react-native-svg"
|
||||
RNVectorIcons:
|
||||
:path: "../node_modules/react-native-vector-icons"
|
||||
RNWatch:
|
||||
:path: "../node_modules/react-native-watch-connectivity"
|
||||
SentryReactNative:
|
||||
:path: "../node_modules/react-native-sentry"
|
||||
ToolTipMenu:
|
||||
:path: "../node_modules/react-native-tooltip"
|
||||
yoga:
|
||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
|
||||
BVLinearGradient: b0b70acf63ee888829b7c2ebbf6b50e227396e55
|
||||
DoubleConversion: bb338842f62ab1d708ceb63ec3d999f0f3d98ecd
|
||||
EFQRCode: 07437cfbce3a1e497397a4f3d766c980d8972608
|
||||
Folly: de497beb10f102453a1afa9edbf8cf8a251890de
|
||||
glog: aefd1eb5dda2ab95ba0938556f34b98e2da3a60d
|
||||
React: 1d605e098d69bdf08960787f3446f0a9dc2e2ccf
|
||||
react-native-camera: 9c50d7def800895e7991ccda6203929553ceec9c
|
||||
react-native-google-analytics-bridge: 0a86be2860b81a3562fe60ac40c0ad732340046f
|
||||
react-native-haptic-feedback: f675486e3889e3229272158943c1e9e075247e5a
|
||||
react-native-image-picker: f42de90075c5b1af53417af927631d909a1a746e
|
||||
react-native-randombytes: d3184d351604f78e019535178766590188bbc133
|
||||
react-native-slider: 743940825f1fa1b37e8396ffd8cebe41f4967e1f
|
||||
react-native-webview: a42108b827082f8f0333529b0772102031d5960d
|
||||
RNCAsyncStorage: 289488409d0c42f30e12535e3f45c5bd3cfc73d2
|
||||
RNDeviceInfo: 08dd79c5adef48b6dc103bf3ddf208039aa78664
|
||||
RNFS: bbb1a64eb245763daf34aea86f97c97c4e85f74c
|
||||
RNGestureHandler: 7ccf2f3f60458e084f9ada01fbaf610f6fef073c
|
||||
RNRate: 72b5c9c2e62de9a01710918eb83d75fb99b44c7b
|
||||
RNSVG: 4834be1d644eb77f0e3f6de851881b83758a3124
|
||||
RNVectorIcons: 8c52e1e8da1153613fdef44748e865c25556cb9c
|
||||
RNWatch: 394c44f35352309ab414daaadfa3c55a4a5224ee
|
||||
Sentry: 4e8a17b61ddd116f89536cc81d567fdee1ebca96
|
||||
SentryReactNative: fc630be25b30c1a494b478ba1fa38f761cc6da20
|
||||
swift_qrcodejs: 0bacbfe321a99954c7b8e04c75562007ea4e4f7c
|
||||
ToolTipMenu: a01f5df49eb1a1ffbc5e1e81d2ec42b832436421
|
||||
yoga: 128daf064cacaede0c3bb27424b6b4c71052e6cd
|
||||
|
||||
PODFILE CHECKSUM: 40fe32f25e14511848fc633565a8030139a972fa
|
||||
|
||||
COCOAPODS: 1.5.3
|
26
ios/Pods/Local Podspecs/RNDeviceInfo.podspec.json
generated
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "RNDeviceInfo",
|
||||
"version": "1.6.0",
|
||||
"summary": "Get device information using react-native",
|
||||
"license": "MIT",
|
||||
"authors": {
|
||||
"name": "Rebecca Hughes",
|
||||
"email": "rebecca@learnium.net",
|
||||
"url": "https://github.com/rebeccahughes"
|
||||
},
|
||||
"homepage": "git+https://github.com/react-native-community/react-native-device-info.git",
|
||||
"platforms": {
|
||||
"ios": "9.0",
|
||||
"tvos": "10.0"
|
||||
},
|
||||
"source": {
|
||||
"git": "https://github.com/react-native-community/react-native-device-info.git",
|
||||
"tag": "1.6.0"
|
||||
},
|
||||
"source_files": "ios/**/*.{h,m}",
|
||||
"dependencies": {
|
||||
"React": [
|
||||
|
||||
]
|
||||
}
|
||||
}
|
23
ios/Pods/Local Podspecs/RNSVG.podspec.json
generated
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "RNSVG",
|
||||
"version": "9.4.0",
|
||||
"summary": "SVG library for react-native",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/react-native-community/react-native-svg",
|
||||
"authors": "Horcrux Chen",
|
||||
"source": {
|
||||
"git": "https://github.com/react-native-community/react-native-svg.git",
|
||||
"tag": "9.4.0"
|
||||
},
|
||||
"source_files": "ios/**/*.{h,m}",
|
||||
"requires_arc": true,
|
||||
"platforms": {
|
||||
"ios": "8.0",
|
||||
"tvos": "9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"React": [
|
||||
|
||||
]
|
||||
}
|
||||
}
|
565
ios/Pods/Local Podspecs/React.podspec.json
generated
Normal file
|
@ -0,0 +1,565 @@
|
|||
{
|
||||
"name": "React",
|
||||
"version": "0.59.6",
|
||||
"summary": "A framework for building native apps using React",
|
||||
"description": "React Native apps are built using the React JS\nframework, and render directly to native UIKit\nelements using a fully asynchronous architecture.\nThere is no browser and no HTML. We have picked what\nwe think is the best set of features from these and\nother technologies to build what we hope to become\nthe best product development framework available,\nwith an emphasis on iteration speed, developer\ndelight, continuity of technology, and absolutely\nbeautiful and fast products with no compromises in\nquality or capability.",
|
||||
"homepage": "http://facebook.github.io/react-native/",
|
||||
"license": "MIT",
|
||||
"authors": "Facebook",
|
||||
"source": {
|
||||
"git": "https://github.com/facebook/react-native.git",
|
||||
"tag": "v0.59.6"
|
||||
},
|
||||
"default_subspecs": "Core",
|
||||
"requires_arc": true,
|
||||
"platforms": {
|
||||
"ios": "9.0",
|
||||
"tvos": "9.2"
|
||||
},
|
||||
"pod_target_xcconfig": {
|
||||
"CLANG_CXX_LANGUAGE_STANDARD": "c++14"
|
||||
},
|
||||
"preserve_paths": [
|
||||
"package.json",
|
||||
"LICENSE",
|
||||
"LICENSE-docs"
|
||||
],
|
||||
"cocoapods_version": ">= 1.2.0",
|
||||
"subspecs": [
|
||||
{
|
||||
"name": "Core",
|
||||
"dependencies": {
|
||||
"yoga": [
|
||||
"0.59.6.React"
|
||||
]
|
||||
},
|
||||
"source_files": "React/**/*.{c,h,m,mm,S,cpp}",
|
||||
"exclude_files": [
|
||||
"**/__tests__/*",
|
||||
"IntegrationTests/*",
|
||||
"React/DevSupport/*",
|
||||
"React/Inspector/*",
|
||||
"ReactCommon/yoga/*",
|
||||
"React/Cxx*/*",
|
||||
"React/Fabric/**/*"
|
||||
],
|
||||
"ios": {
|
||||
"exclude_files": "React/**/RCTTV*.*"
|
||||
},
|
||||
"tvos": {
|
||||
"exclude_files": [
|
||||
"React/Modules/RCTClipboard*",
|
||||
"React/Views/RCTDatePicker*",
|
||||
"React/Views/RCTPicker*",
|
||||
"React/Views/RCTRefreshControl*",
|
||||
"React/Views/RCTSlider*",
|
||||
"React/Views/RCTSwitch*",
|
||||
"React/Views/RCTWebView*"
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"header_dir": "React",
|
||||
"frameworks": "JavaScriptCore",
|
||||
"libraries": "stdc++",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "CxxBridge",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
],
|
||||
"React/Core": [
|
||||
|
||||
],
|
||||
"React/cxxreact": [
|
||||
|
||||
],
|
||||
"React/jsiexecutor": [
|
||||
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"private_header_files": "React/Cxx*/*.h",
|
||||
"source_files": "React/Cxx*/*.{h,m,mm}"
|
||||
},
|
||||
{
|
||||
"name": "DevSupport",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
],
|
||||
"React/RCTWebSocket": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": [
|
||||
"React/DevSupport/*",
|
||||
"React/Inspector/*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "RCTFabric",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
],
|
||||
"React/Core": [
|
||||
|
||||
],
|
||||
"React/fabric": [
|
||||
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "React/Fabric/**/*.{c,h,m,mm,S,cpp}",
|
||||
"exclude_files": "**/tests/*",
|
||||
"header_dir": "React",
|
||||
"frameworks": "JavaScriptCore",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tvOS",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "React/**/RCTTV*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "jsinspector",
|
||||
"source_files": "ReactCommon/jsinspector/*.{cpp,h}",
|
||||
"private_header_files": "ReactCommon/jsinspector/*.h",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "jsiexecutor",
|
||||
"dependencies": {
|
||||
"React/cxxreact": [
|
||||
|
||||
],
|
||||
"React/jsi": [
|
||||
|
||||
],
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
],
|
||||
"DoubleConversion": [
|
||||
|
||||
],
|
||||
"glog": [
|
||||
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/jsiexecutor/jsireact/*.{cpp,h}",
|
||||
"private_header_files": "ReactCommon/jsiexecutor/jsireact/*.h",
|
||||
"header_dir": "jsireact",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\", \"$(PODS_TARGET_SRCROOT)/ReactCommon/jsiexecutor\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "jsi",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
],
|
||||
"DoubleConversion": [
|
||||
|
||||
],
|
||||
"glog": [
|
||||
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/jsi/*.{cpp,h}",
|
||||
"private_header_files": "ReactCommon/jsi/*.h",
|
||||
"frameworks": "JavaScriptCore",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "PrivateDatabase",
|
||||
"source_files": "ReactCommon/privatedata/*.{cpp,h}",
|
||||
"private_header_files": "ReactCommon/privatedata/*.h",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cxxreact",
|
||||
"dependencies": {
|
||||
"React/jsinspector": [
|
||||
|
||||
],
|
||||
"boost-for-react-native": [
|
||||
"1.63.0"
|
||||
],
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
],
|
||||
"DoubleConversion": [
|
||||
|
||||
],
|
||||
"glog": [
|
||||
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/cxxreact/*.{cpp,h}",
|
||||
"exclude_files": "ReactCommon/cxxreact/SampleCxxModule.*",
|
||||
"private_header_files": "ReactCommon/cxxreact/*.h",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "fabric",
|
||||
"subspecs": [
|
||||
{
|
||||
"name": "activityindicator",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/fabric/activityindicator/**/*.{cpp,h}",
|
||||
"exclude_files": "**/tests/*",
|
||||
"header_dir": "fabric/activityindicator",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "attributedstring",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/fabric/attributedstring/**/*.{cpp,h}",
|
||||
"exclude_files": "**/tests/*",
|
||||
"header_dir": "fabric/attributedstring",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "core",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/fabric/core/**/*.{cpp,h}",
|
||||
"exclude_files": "**/tests/*",
|
||||
"header_dir": "fabric/core",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "debug",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/fabric/debug/**/*.{cpp,h}",
|
||||
"exclude_files": "**/tests/*",
|
||||
"header_dir": "fabric/debug",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "graphics",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/fabric/graphics/**/*.{cpp,h}",
|
||||
"exclude_files": "**/tests/*",
|
||||
"header_dir": "fabric/graphics",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "scrollview",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/fabric/scrollview/**/*.{cpp,h}",
|
||||
"exclude_files": "**/tests/*",
|
||||
"header_dir": "fabric/scrollview",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "text",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/fabric/text/**/*.{cpp,h}",
|
||||
"exclude_files": "**/tests/*",
|
||||
"header_dir": "fabric/text",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "textlayoutmanager",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/fabric/textlayoutmanager/**/*.{cpp,h,mm}",
|
||||
"exclude_files": "**/tests/*",
|
||||
"header_dir": "fabric/textlayoutmanager",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uimanager",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/fabric/uimanager/**/*.{cpp,h}",
|
||||
"exclude_files": "**/tests/*",
|
||||
"header_dir": "fabric/uimanager",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "view",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
],
|
||||
"yoga": [
|
||||
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/fabric/view/**/*.{cpp,h}",
|
||||
"exclude_files": "**/tests/*",
|
||||
"header_dir": "fabric/view",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "RCTFabricSample",
|
||||
"dependencies": {
|
||||
"Folly": [
|
||||
"2018.10.22.00"
|
||||
]
|
||||
},
|
||||
"compiler_flags": "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"source_files": "ReactCommon/fabric/sample/**/*.{cpp,h}",
|
||||
"exclude_files": "**/tests/*",
|
||||
"header_dir": "fabric/sample",
|
||||
"pod_target_xcconfig": {
|
||||
"HEADER_SEARCH_PATHS": "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ART",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/ART/**/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "RCTActionSheet",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/ActionSheetIOS/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "RCTAnimation",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/NativeAnimation/{Drivers/*,Nodes/*,*}.{h,m}",
|
||||
"header_dir": "RCTAnimation"
|
||||
},
|
||||
{
|
||||
"name": "RCTBlob",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/Blob/*.{h,m,mm}",
|
||||
"preserve_paths": "Libraries/Blob/*.js"
|
||||
},
|
||||
{
|
||||
"name": "RCTCameraRoll",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
],
|
||||
"React/RCTImage": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/CameraRoll/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "RCTGeolocation",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/Geolocation/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "RCTImage",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
],
|
||||
"React/RCTNetwork": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/Image/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "RCTNetwork",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/Network/*.{h,m,mm}"
|
||||
},
|
||||
{
|
||||
"name": "RCTPushNotification",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/PushNotificationIOS/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "RCTSettings",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/Settings/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "RCTText",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/Text/**/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "RCTVibration",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/Vibration/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "RCTWebSocket",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
],
|
||||
"React/RCTBlob": [
|
||||
|
||||
],
|
||||
"React/fishhook": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/WebSocket/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "fishhook",
|
||||
"header_dir": "fishhook",
|
||||
"source_files": "Libraries/fishhook/*.{h,c}"
|
||||
},
|
||||
{
|
||||
"name": "RCTLinkingIOS",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/LinkingIOS/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "RCTTest",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"source_files": "Libraries/RCTTest/**/*.{h,m}",
|
||||
"frameworks": "XCTest"
|
||||
},
|
||||
{
|
||||
"name": "_ignore_me_subspec_for_linting_",
|
||||
"dependencies": {
|
||||
"React/Core": [
|
||||
|
||||
],
|
||||
"React/CxxBridge": [
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
97
ios/Pods/Local Podspecs/react-native-camera.podspec.json
generated
Normal file
|
@ -0,0 +1,97 @@
|
|||
{
|
||||
"name": "react-native-camera",
|
||||
"version": "2.6.0",
|
||||
"summary": "A Camera component for React Native. Also reads barcodes.",
|
||||
"description": "A Camera component for React Native. Also reads barcodes.",
|
||||
"license": "MIT AND Apache-2.0 AND BSD-3-Clause",
|
||||
"authors": {
|
||||
"name": "Lochlan Wansbrough",
|
||||
"email": "lochie@live.com",
|
||||
"url": "http://lwansbrough.com"
|
||||
},
|
||||
"homepage": "https://github.com/react-native-community/react-native-camera",
|
||||
"source": {
|
||||
"git": "https://github.com/react-native-community/react-native-camera",
|
||||
"tag": "v2.6.0"
|
||||
},
|
||||
"requires_arc": true,
|
||||
"platforms": {
|
||||
"ios": "9.0"
|
||||
},
|
||||
"default_subspecs": [
|
||||
"RN",
|
||||
"RCT"
|
||||
],
|
||||
"preserve_paths": [
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"package.json",
|
||||
"index.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"React": [
|
||||
|
||||
]
|
||||
},
|
||||
"subspecs": [
|
||||
{
|
||||
"name": "RCT",
|
||||
"source_files": "ios/RCT/**/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "RN",
|
||||
"source_files": "ios/RN/**/*.{h,m}"
|
||||
},
|
||||
{
|
||||
"name": "TextDetector",
|
||||
"dependencies": {
|
||||
"react-native-camera/RN": [
|
||||
|
||||
],
|
||||
"react-native-camera/RCT": [
|
||||
|
||||
],
|
||||
"Firebase/MLVision": [
|
||||
|
||||
],
|
||||
"Firebase/MLVisionTextModel": [
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "FaceDetectorMLKit",
|
||||
"dependencies": {
|
||||
"react-native-camera/RN": [
|
||||
|
||||
],
|
||||
"react-native-camera/RCT": [
|
||||
|
||||
],
|
||||
"Firebase/MLVision": [
|
||||
|
||||
],
|
||||
"Firebase/MLVisionFaceModel": [
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "BarcodeDetectorMLKit",
|
||||
"dependencies": {
|
||||
"react-native-camera/RN": [
|
||||
|
||||
],
|
||||
"react-native-camera/RCT": [
|
||||
|
||||
],
|
||||
"Firebase/MLVision": [
|
||||
|
||||
],
|
||||
"Firebase/MLVisionBarcodeModel": [
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|