Commit 4c8579a4 authored by Allan Juma's avatar Allan Juma

0.6.2

parent a57149cd
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
### Description
### Steps to reproduce the behavior
### Expected behavior
### Actual behavior
### Screenshot and/or logs if applicable
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
......@@ -85,8 +85,8 @@ ipcMain.on('logs-ready', () => {
function createWindow() {
console.log(path.join(__dirname, 'preload.js'));
const options = {
width: 850,
height: 705,
width: 650,
height: 950,
backgroundColor: '#0f5f76',
icon: path.join(
__dirname,
......@@ -107,7 +107,7 @@ console.log(path.join(__dirname, 'preload.js'));
if (isDev) {
// Add width for dev tools
options.width += 720;
options.height += 450;
options.height += 0;
win = new BrowserWindow(options);
win.loadURL('http://localhost:3000');
// Open the DevTools.
......
......@@ -112,11 +112,11 @@ module.exports.startLndProcess = async function({
if (isDev) {
args = args.concat([
'--bitcoin.node=bitcoind',
'--bitcoind.rpchost=192.168.1.3',
'--bitcoind.rpchost=btc-p2p.bitsoko.org',
'--bitcoind.rpcuser=bitsoko',
'--bitcoind.rpcpass=12Bitcoinsrus12',
'--bitcoind.zmqpubrawblock=tcp://192.168.1.3:28332',
'--bitcoind.zmqpubrawtx=tcp://192.168.1.3:28333'
'--bitcoind.zmqpubrawblock=tcp://btc-p2p.bitsoko.org:28332',
'--bitcoind.zmqpubrawtx=tcp://btc-p2p.bitsoko.org:28333'
]);
}
......
......@@ -17,6 +17,7 @@ import LogAction from './log';
import InfoAction from './info';
import NotificationAction from './notification';
import ChannelAction from './channel';
import InvestmentAction from './investment';
import TransactionAction from './transaction';
import DaoAction from './dao';
import PoolAction from './pool';
......@@ -51,6 +52,7 @@ export const info = new InfoAction(store, grpc, nav, notify);
export const pool = new PoolAction(store, grpc, nav, notify);
export const dao = new DaoAction(store, grpc, nav, notify);
export const promotion = new PromotionAction(store, grpc, nav, notify);
export const investment = new InvestmentAction(store, grpc, nav, notify);
export const transaction = new TransactionAction(store, grpc, nav, notify);
export const channel = new ChannelAction(store, grpc, nav, notify);
export const invoice = new InvoiceAction(store, grpc, nav, notify, Clipboard);
......@@ -123,29 +125,63 @@ when(
* the user can really begin to interact with the application and calls
* to and from lnd can be done. The contract chains are implemented
*/
function setChainAccount(chain, account) {
if (!store.settings.chains[chain]) {
throw new Error(`Invalid chain: `+chain);
}
if (!account) {
throw new Error(`Invalid seed: `+account);
}
store.settings.chains[chain].account = account;
db.save();
console.log('INFO! '+chain+' account '+account.address);
}
function setChainAddress(chain, addr) {
if (!store.settings.chains[chain]) {
throw new Error(`Invalid chain: `+chain);
}
if (!addr) {
throw new Error(`Invalid address: `+addr);
}
store.settings.chains[chain].addresses.push(addr);
db.save();
}
when(
() => store.lndReady,
async () => {
console.log(store.settings.chains);
if(!store.chains.algo.account){
if(!store.settings.chains.algo.account){
var algoAccount = await Algorand.createWallet();
store.chains.algo.account = algoAccount;
//var algoAccountInfo = await Algorand.getAccount('testnet',store.chains.algo.account.address);
setChainAccount('algo', algoAccount);
console.log('new algo account! '+store.settings.chains.algo.account.address);
}else{
console.log('old algo account! '+store.settings.chains.algo.account.address);
}
console.log('INFO! algorand account '+store.chains.algo.account.address);
/*
if(!store.chains.sol.account){
var solAccount = await Solana.createWallet();
store.chains.sol.account = solAccount;
//var solAccountInfo = await Solana.getAccount('testnet',store.chains.sol.account.address);
setChainAccount({chain:'sol', account:solAccount});
}
console.log('INFO! solana account '+store.chains.sol.account.address);
*/
}
);
......
/**
* @fileOverview actions to set Investments state within the app and to
* call the corresponding apis for listing transactions.
*/
import * as log from './log';
import { parseDate, toHex } from '../helper';
class InvestmentAction {
constructor(store, grpc, nav, notification) {
this._store = store;
this._grpc = grpc;
this._nav = nav;
this._notification = notification;
}
/**
* Initiate the transaction list view by navigating to the view and updating
* the app's transaction state by calling all necessary grpc apis.
* @return {undefined}
*/
init() {
this._nav.goInvestments();
this.update();
}
/**
* Select a transaction item from the transaction list view and then navigate
* to the detail view to list transaction parameters.
* @param {Object} options.item The selected transaction object
* @return {Promise<undefined>}
*/
async select({ item }) {
this._store.selectedTransaction = item;
if (item.paymentRequest) {
item.memo = await this.decodeMemo({ payReq: item.paymentRequest });
}
this._nav.goTransactionDetail();
this.update();
}
/**
* Update the on-chain transactions, invoice, and lighting payments in the
* app state by querying all required grpc apis.
* @return {Promise<undefined>}
*/
async update() {
await Promise.all([
this.getAlgoTransactions(),
]);
}
/**
* Get lock state.
* @return {Promise<undefined>}
*/
async updateLock(TransactionTime) {
let locked=true;
if(TransactionTime < new Date().setDate(new Date().getDate() - 1)){
locked=false;
}
return locked;
}
/**
* List the on-chain transactions by calling the respective grpc api and updating
* the transactions array in the global store.
* @return {Promise<undefined>}
*/
async getAlgoTransactions() {
try {
const { transactions } = await this._grpc.sendCommand('listInvoices');
this._store.transactions = transactions.map(transaction => ({
id: transaction.txHash,
type: this.updateLock(transaction.timeStamp) ? 'locked' : 'unlocked',
amount: transaction.amount,
fee: transaction.totalFees,
confirmations: transaction.numConfirmations,
status: transaction.numConfirmations < 3 ? 'rewarded' : 'confirmed',
date: parseDate(transaction.timeStamp),
}));
} catch (err) {
log.error('Listing transactions failed', err);
}
}
/**
* Subscribe to incoming on-chain transactions using the grpc streaming api.
* @return {Promise<undefined>}
*/
async subscribeTransactions() {
const stream = this._grpc.sendStreamCommand('subscribeTransactions');
await new Promise((resolve, reject) => {
stream.on('data', () => this.update());
stream.on('end', resolve);
stream.on('error', reject);
stream.on('status', status => log.info(`Transactions update: ${status}`));
});
}
}
export default InvestmentAction;
......@@ -167,6 +167,10 @@ class NavAction {
goTransactions() {
this._store.route = 'Transactions';
}
goInvestments() {
this._store.route = 'Investments';
}
goPools() {
this._store.route = 'Pools';
......@@ -189,6 +193,12 @@ class NavAction {
this._store.route = 'Notifications';
}
goContractSettings(contract) {
this._store.selectedContractSetting = contract;
this._store.route = 'SetContract';
}
goSettings() {
this._store.route = 'Settings';
}
......
......@@ -139,7 +139,7 @@ class PoolAddAction {
const { settings } = this._store;
var amount = toSatoshis(amount, settings);
//get new pool quotation from server
var escrowInvoice = await sendToEscrow(amount, '{"state":"pool","action":"add","account":"algo1","pool":"pool1"}');
var escrowInvoice = await sendToEscrow(amount, '{"state":"pool", "action":"add", "account":"'+this._store.settings.chains.algo.account.address+'", "pool":"'+this._store.selectedPool.id+'", "type":"float"}');
console.log(escrowInvoice);
this.setAddress({ address: escrowInvoice });
......
......@@ -60,20 +60,24 @@ class PoolAction {
async getPools() {
try {
const uri = 'https://gateway.bitsoko.org/getEnterprise/?servEntID=1';
const uri =
'https://gateway.bitsoko.org/getEnterpriseRoute';
//const uri = 'https://gateway.bitsoko.org/getEnterpriseRoute';
const response = checkHttpStatus(await fetch(uri));
const pools = await response.json();
const svs = await response.json();
var pools = svs.services;
//const pools = (await response.json()).tickers;
//const rate = tickers.find(t => t.ticker.toLowerCase() === fiat).rate;
this._store.pools = pools.map(pool => ({
id: pool.url,
id: pool.id,
cat: 'micro',
type: 'algorand',
title: pool.title ? pool.title : 'Sample merchant @ https://demo1.bitsoko.org',
desc: pool.desc ? pool.desc : '{name:"demo", desc:"a sample merchant", image:"",banner:"",link:"",url:"https://demo1.bitsoko.org"}',
icon: pool.bannerPath,
banner: pool.bannerPath,
url: 'https://demo1.bitsoko.org',
title: pool.name,
desc: pool.description,
amount: 0,
fee: 0,
confirmations: 5,
......
......@@ -115,22 +115,69 @@ const countStyles = StyleSheet.create({
paddingRight: 10,
paddingLeft: 10,
borderRadius: 13,
},
red: {
backgroundColor: color.pinkSig,
},
orange: {
backgroundColor: color.orangeSig,
},
green: {
backgroundColor: color.greenSig,
},
grey: {
backgroundColor: color.greySig,
},
txt: {
fontSize: font.sizeXS,
lineHeight: font.lineHeightXS,
},
});
export const CountBubble = ({ children, style }) =>
export const CountBubbleRed = ({ children, style }) =>
children && children !== '0' ? (
<View style={[countStyles.red, countStyles.bubble, style]}>
<H4Text style={countStyles.txt}>{children}</H4Text>
</View>
) : null;
export const CountBubbleGreen = ({ children, style }) =>
children && children !== '0' ? (
<View style={[countStyles.green, countStyles.bubble, style]}>
<H4Text style={countStyles.txt}>{children}</H4Text>
</View>
) : null;
export const CountBubbleOrange = ({ children, style }) =>
children && children !== '0' ? (
<View style={[countStyles.bubble, style]}>
<View style={[countStyles.orange, countStyles.bubble, style]}>
<H4Text style={countStyles.txt}>{children}</H4Text>
</View>
) : null;
CountBubble.propTypes = {
export const CountBubbleGrey = ({ children, style }) =>
children && children !== '0' ? (
<View style={[countStyles.bubble, countStyles.grey, style]}>
<H4Text style={countStyles.txt}>{children}</H4Text>
</View>
) : null;
CountBubbleRed.propTypes = {
children: PropTypes.string.isRequired,
style: ViewPropTypes.style,
};
CountBubbleOrange.propTypes = {
children: PropTypes.string.isRequired,
style: ViewPropTypes.style,
};
CountBubbleGreen.propTypes = {
children: PropTypes.string.isRequired,
style: ViewPropTypes.style,
};
CountBubbleGrey.propTypes = {
children: PropTypes.string.isRequired,
style: ViewPropTypes.style,
};
......
......@@ -7,7 +7,7 @@ import {
} from 'react-native';
import PropTypes from 'prop-types';
import { color, font } from './style';
import LightningBoltIcon from '../asset/icon/lightning-bolt';
import BitcoinIcon from '../../src/asset/icon/bitcoin';
import Text from './text';
import Svg, { Path, Circle, Defs, Stop, LinearGradient } from './svg';
import { generateArc } from '../helper';
......@@ -53,7 +53,8 @@ export const LoadNetworkSpinner = ({ continuous, percentage, msg, style }) => (
progressWidth={3}
gradient="loadNetworkGrad"
>
<LightningBoltIcon height={28} width={14.2222} />
<BitcoinIcon height={38} width={25} />
</ResizeableSpinner>
<Text style={loadNetworkStyles.copy}>{msg}</Text>
</View>
......
......@@ -89,6 +89,23 @@ const ComputedChannel = store => {
? 'info'
: 'error';
},
get contractStatus() {
const {
channelBalanceOpenSatoshis: opened,
channelBalanceInactiveSatoshis: inactive,
channelBalancePendingSatoshis: pending,
} = store;
return 'info';
/*
return opened
? 'success'
: inactive
? 'inactive'
: pending
? 'info'
: 'error';
*/
},
});
};
......
......@@ -16,9 +16,9 @@ const ComputedPool = store => {
all.sort((a, b) => b.date.getTime() - a.date.getTime());
all.forEach((t, i) => {
t.key = String(i);
t.idName = t.type === 'algorand' ? 'Algorand' : 'Ethereum';
//t.icon = '../asset/icon/'+t.type+'.png';
t.icon = '../asset/icon/lightning.svg';
//t.idName = t.type === 'algorand' ? '209:BITS:dooca-net' : 'Ethereum';
t.idName = t.id+':BITS:dooca.net | '+t.title;
t.icon = t.icon;
t.typeLabel = toCaps(t.type);
t.statusLabel = toCaps(t.status);
t.merchantLabel = t.title;
......
......@@ -63,28 +63,6 @@ export class Store {
restoreIndex: 0,
focusedRestoreInd: 0,
},
chains: {
eth:{
account:'',
rpc:{mainnet: {server:'',port:'',key:''}, testnet: {server:'',port:'',key:''}}
},
matic:{
account:'',
rpc:{mainnet: {server:'',port:'',key:''}, testnet: {server:'',port:'',key:''}}
},
xml:{
account:'',
rpc:{mainnet: {server:'',port:'',key:''}, testnet: {server:'',port:'',key:''}}
},
sol:{
account:'',
rpc:{mainnet: {server:'',port:'',key:''}, testnet: {server:'',port:'',key:''}}
},
algo:{
account:'',
rpc:{mainnet: {server:'',port:'',key:''}, testnet: {server:'https://testnet-algorand.api.purestake.io/ps2',port:'',key:'qe3CNhIJ3C5DXrGHlfxAU1aIUt7SrYzNMwHz8gKb'}}
},
},
promotions: [],
selectedPromotion: null,
pools: [],
......@@ -127,6 +105,7 @@ export class Store {
// Persistent data
settings: {
contracts: ['algo','eth'],
unit: DEFAULT_UNIT,
fiat: DEFAULT_FIAT,
displayFiat: true,
......@@ -134,6 +113,14 @@ export class Store {
restoring: false,
autopilot: true,
nodeScores: {},
chains: {
algo:{
account:false,
chain: 'testnet',
addresses: [],
rpc:{mainnet: {server:'',port:'',key:''}, testnet: {server:'https://testnet-algorand.api.purestake.io/ps2',port:'',key:'qe3CNhIJ3C5DXrGHlfxAU1aIUt7SrYzNMwHz8gKb'}}
}
}
},
});
}
......
......@@ -74,6 +74,8 @@ const HomeView = ({
unitLabel,
channelStatus,
channelPercentageLabel,
contractStatus,
contractPercentageLabel,
} = store;
return (
<Background image="purple-gradient-bg">
......@@ -89,6 +91,8 @@ const HomeView = ({
unitLabel={unitLabel}
channelStatus={channelStatus}
channelPercentageLabel={channelPercentageLabel}
contractStatus={contractStatus}
contractPercentageLabel={contractPercentageLabel}
toggleDisplayFiat={() => wallet.toggleDisplayFiat()}
goChannels={() => channel.init()}
/>
......@@ -137,6 +141,7 @@ const balanceStyles = StyleSheet.create({
},
alert: {
marginRight: 6,
marginLeft: '50%',
},
});
......@@ -146,6 +151,8 @@ const BalanceDisplay = ({
unitLabel,
channelStatus,
channelPercentageLabel,
contractStatus,
contractPercentageLabel,
toggleDisplayFiat,
goChannels,
}) => (
......@@ -159,8 +166,17 @@ const BalanceDisplay = ({
<Button onPress={goChannels} style={balanceStyles.percentBtn}>
<View style={{flex:2,flexDirection:"column",justifyContent:"center",width:"100%",padding:10,paddingTop:50,textAlign:"center"}}>
<View style={{flex:1,padding:10,marginTop: "-10px"}}>
<Alert type={channelStatus} style={balanceStyles.alert} />
<H4Text>{channelPercentageLabel}</H4Text>
<H4Text style={{paddingTop: "5px"}}>{channelPercentageLabel}{"\n"}</H4Text>
</View>
<View style={{flex:1,padding:10,marginTop: "-10px"}}>
<Alert type={contractStatus} style={balanceStyles.alert} />
<H4Text style={{paddingTop: "5px"}}>0% on Contracts</H4Text>
</View>
</View>
</Button>
</View>
);
......@@ -170,6 +186,8 @@ BalanceDisplay.propTypes = {
unitLabel: PropTypes.string,
channelStatus: PropTypes.string.isRequired,
channelPercentageLabel: PropTypes.string.isRequired,
contractStatus: PropTypes.string.isRequired,
contractPercentageLabel: PropTypes.string.isRequired,
toggleDisplayFiat: PropTypes.func.isRequired,
goChannels: PropTypes.func.isRequired,
};
......
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { observer } from 'mobx-react';
import PropTypes from 'prop-types';
import Background from '../component/background';
import { Header, Title } from '../component/header';
import { Button, CancelButton } from '../component/button';
import { ListContent, List, ListItem, ListHeader } from '../component/list';
import { Alert } from '../component/notification';
import Text from '../component/text';
import BitcoinIcon from '../../src/asset/icon/bitcoin';
import LightningBoltIcon from '../../src/asset/icon/lightning-bolt';
import { color, font } from '../component/style';
//
// Investment View
//
const InvestmentView = ({ store, nav, transaction }) => {
const { computedTransactions: transactions } = store;
return (
<Background color={color.blackDark}>
<Header separator>
<Button disabled onPress={() => {}} />
<Title title="Investments" />
<CancelButton onPress={() => nav.goPools()} />
</Header>
<ListContent>
<List
data={transactions}
renderHeader={InvestmentListHeader}
renderItem={item => (
<InvestmentListItem
tx={item}
onSelect={() => transaction.select({ item })}
/>
)}
/>
</ListContent>
</Background>
);
};
InvestmentView.propTypes = {
store: PropTypes.object.isRequired,
nav: PropTypes.object.isRequired,
transaction: PropTypes.object.isRequired,
};
//
// Transaction List Item
//
const iStyles = StyleSheet.create({
item: {
paddingLeft: 10,
paddingRight: 10,
},
wrap: {
paddingRight: 50,
},
txt: {
color: color.white,
fontSize: font.sizeS,
},
alert: {
marginRight: 6,
},
group: {
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
},
l: { flex: 8 },
m: { flex: 4 },
s: { flex: 2 },
i: { flex: 1 },
});
const statusType = tx => {
if (tx.type === 'locked') {
return tx.status === 'rewarded' ? 'success' : 'error';
} else {
return tx.status === 'rewarded' ? 'success' : 'info';
}
};
const InvestmentListItem = ({ tx, onSelect }) => (
<ListItem style={iStyles.item} onSelect={onSelect}>
<View style={iStyles.i}>
{(tx.type === 'unlocked' && tx.status === 'rewarded') ? (
<LightningBoltIcon height={126 * 0.14} width={64 * 0.14} />
) : (
<BitcoinIcon height={170 * 0.08} width={135 * 0.08} />
)}
</View>
<View style={[iStyles.m, iStyles.group]}>
<Alert type={statusType(tx)} style={iStyles.alert} />
<Text style={iStyles.txt}>{tx.statusLabel}</Text>
</View>
<Text style={[iStyles.m, iStyles.txt]}>{tx.dateLabel}</Text>
<View style={iStyles.l}>
<Text style={[iStyles.txt, iStyles.wrap]} numberOfLines={1}>
{tx.id}
</Text>
</View>
<Text style={[iStyles.m, iStyles.txt]}>{tx.amountLabel}</Text>
<Text style={[iStyles.s, iStyles.txt]}>{tx.feeLabel}</Text>
</ListItem>
);
InvestmentListItem.propTypes = {
tx: PropTypes.object.isRequired,
onSelect: PropTypes.func.isRequired,
};
//
// Transaction List Header
//
const hStyles = StyleSheet.create({
txt: {
color: color.greyListHeader,
fontSize: font.sizeXS,
},
header: {
backgroundColor: color.blackDark,
},
});
const InvestmentListHeader = () => (
<ListHeader style={[iStyles.item, hStyles.header]}>
<View style={iStyles.i} />
<Text style={[iStyles.m, hStyles.txt]}>STATUS</Text>
<Text style={[iStyles.m, hStyles.txt]}>DATE</Text>
<Text style={[iStyles.l, hStyles.txt]}>CONTRACT ID</Text>
<Text style={[iStyles.m, hStyles.txt]}>AMOUNT</Text>
<Text style={[iStyles.s, hStyles.txt]}>FEE</Text>
</ListHeader>
);
export default observer(InvestmentView);
......@@ -40,12 +40,14 @@ import ChannelDetail from './channel-detail';
import ChannelDelete from './channel-delete';
import ChannelCreate from './channel-create';
import PoolAdd from './pool-add';
import Investment from './investment';
import Transaction from './transaction';
import Promotion from './promotion';
import Pool from './pool';
import Setting from './setting';
import SettingUnit from './setting-unit';
import SettingFiat from './setting-fiat';
import SetContract from './set-contract';
import Notification from './notification';
import CLI from './cli';
import TransactionDetail from './transaction-detail';
......@@ -57,6 +59,7 @@ import {
payment,
invoice,
channel,
investment,
transaction,
promotion,
setting,
......@@ -144,6 +147,7 @@ class MainView extends Component {
<SettingFiat store={store} nav={nav} setting={setting} />
)}
{route === 'Notifications' && <Notification store={store} nav={nav} />}
{route === 'SetContract' && <SetContract store={store} nav={nav} invoice={invoice} />}
{route === 'CLI' && <CLI store={store} nav={nav} />}
{route === 'Pay' && (
<Payment store={store} payment={payment} nav={nav} />
......@@ -200,6 +204,9 @@ class MainView extends Component {
{route === 'PoolAdd' && (
<PoolAdd store={store} channel={channel} nav={nav} />
)}
{route === 'Investments' && (
<Investment store={store} transaction={transaction} nav={nav} />
)}
{route === 'Transactions' && (
<Transaction store={store} transaction={transaction} nav={nav} />
)}
......
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { observer } from 'mobx-react';
import PropTypes from 'prop-types';
import Background from '../component/background';
import { Header, Title } from '../component/header';
import { Button, BackButton, SmallPillButton } from '../component/button';
import { ListContent, List, ListItem, ListHeader } from '../component/list';
import { Alert } from '../component/notification';
import Text from '../component/text';
import { color, font } from '../component/style';
//
// ManageContract View
//
const ManageContractView = ({ store, nav }) => {
const { computedNotifications: notifications } = store;
return (
<Background color={color.blackDark}>
<Header separator>
<BackButton onPress={() => nav.goSettings()} />
<Title title="Notifications" />
<Button disabled onPress={() => {}} />
</Header>
<ListContent>
<List
data={notifications}
renderHeader={ManageContractListHeader}
renderItem={item => <ManageContractListItem item={item} />}
/>
</ListContent>
</Background>
);
};
ManageContractView.propTypes = {
store: PropTypes.object.isRequired,
nav: PropTypes.object.isRequired,
};
//
// Notification List Item
//
const iStyles = StyleSheet.create({
wrap: {
flex: 1,
paddingRight: 50,
},
txt: {
color: color.white,
fontSize: font.sizeS,
},
alert: {
marginRight: 6,
},
group: {
flexDirection: 'row',
alignItems: 'center',
},
l: { flex: 8 },
m: { flex: 3 },
s: { flex: 2 },
i: { flex: 1 },
});
const ManageContractListItem = ({ item }) => (
<ListItem>
<View style={[iStyles.s, iStyles.group]}>
<Alert type={item.type} style={iStyles.alert} />
<Text style={iStyles.txt}>{item.typeLabel}</Text>
</View>
<Text style={[iStyles.m, iStyles.txt]}>{item.dateTimeLabel}</Text>
<View style={[iStyles.l, iStyles.group]}>
<Text style={[iStyles.txt, iStyles.wrap]} numberOfLines={1}>
{item.message}
</Text>
{item.handler ? (
<SmallPillButton text={item.handlerLbl} onPress={item.handler} />
) : null}
</View>
</ListItem>
);
ManageContractListItem.propTypes = {
item: PropTypes.object.isRequired,
};
//
// Notification List Header
//
const hStyles = StyleSheet.create({
txt: {
color: color.greyListHeader,
fontSize: font.sizeXS,
},
header: {
backgroundColor: color.blackDark,
},
});
const ManageContractListHeader = () => (
<ListHeader style={hStyles.header}>
<Text style={[iStyles.s, hStyles.txt]}>TYPE</Text>
<Text style={[iStyles.m, hStyles.txt]}>TIME</Text>
<Text style={[iStyles.l, hStyles.txt]}>DESCRIPTION</Text>
</ListHeader>
);
export default observer(ManageContractView);
......@@ -12,6 +12,8 @@ import Modal from '../component/modal';
import { color } from '../component/style';
import LightningBoltOrangeIcon from '../asset/icon/lightning-bolt-orange';
import { GlasButton, ChannelButton } from '../component/button';
import store from '../store';
import { DEFAULT_FIAT } from '../config';
import Icon from '../component/icon';
......@@ -26,34 +28,35 @@ ChartJS.register(ArcElement, Tooltip, Legend,
Tooltip,
Legend);
const options = {
responsive: true,
plugins: {
legend: {
position: 'top',
},
title: {
display: true,
text: 'performance',
},
},
};
const labels = ['30', '29', '28', '27', '26', '25', '24', '23', '22', '21', '20', '19', '18', '17', '16', '15', '14', '13', '12', '11', '10', '9', '8', '7', '6', '5', '4', '3', '2', '1'];
function newPoolSize(day){
const labels = ['30', '29', '28', '27', '26', '25', '24', '23', '22', '21', '20', '19', '18', '17', '16', '15', '14', '13', '12', '11', '10', '9', '8', '7', '6', '5', '4', '3', '2', '1', 'Today'];
var size = (faker.datatype.number({ min: 1000, max: 1500 })/(Math.log(10+parseInt(day))*faker.datatype.number({ min: 0.65, max: 0.95 })));
return size;
}
export const perfData = {
labels,
datasets: [
{
label: 'Sales',
data: labels.map(() => faker.datatype.number({ min: 0, max: 100 })),
label: 'income',
data: labels.map(() => faker.datatype.number({ min: 400, max: 1000 })),
borderColor: 'rgb(99, 255, 221)',
backgroundColor: 'rgba(99, 255, 221, 0.25)',
},
{
label: 'expenses',
data: labels.map(() => faker.datatype.number({ min: 200, max: 500 })),
borderColor: 'rgb(255, 99, 132)',
backgroundColor: 'rgba(255, 99, 132, 0.5)',
backgroundColor: 'rgba(255, 99, 132, 0.4)',
},
{
label: 'Volume',
data: labels.map(() => faker.datatype.number({ min: 0, max: 1000 })),
label: 'pool (,000)',
data: labels.map(newPoolSize),
borderColor: 'rgb(53, 162, 235)',
backgroundColor: 'rgba(53, 162, 235, 0.5)',
},
......@@ -103,38 +106,64 @@ const iconType = t => {
/>
*/
return require('../asset/icon/'+t+'.png');
};
function dataGen(store, options) {
perfData.datasets[0].data = labels.map(() => faker.datatype.number({ min: 400, max: 1000 }));
perfData.datasets[1].data = labels.map(() => faker.datatype.number({ min: 200, max: 500 }));
perfData.datasets[2].data = labels.map(newPoolSize);
options.plugins.title.text = '30d Volume ('+store.settings.fiat.toLowerCase()+')';
}
const options = {
responsive: true,
plugins: {
legend: {
position: 'top',
},
title: {
display: true,
text: '30d Volume ('+store.settings.fiat.toLowerCase()+')',
},
},
};
const PoolDetailView = ({ store, nav, pooladdliq, poolremoveliq}) => (
<Background color={color.blackDark}>
<MainContent style={styles.content}>
<Modal title="Merchant Pool Details" onClose={() => nav.goPools()}>
<Modal title={store.selectedPool.idName} onClose={() => nav.goPools()}>
<Line options={options} data={perfData} />
<DetailField name={store.selectedPool.idName}>
{store.selectedPool.id}
</DetailField>
<DetailField name="Type">
{store.selectedPool.typeLabel}
<Line meta={ dataGen(store, options) } options={options} data={perfData} />
<DetailField name={store.selectedPool.title}>
{store.selectedPool.desc}
</DetailField>
<DetailField name="Date">
{store.selectedPool.dateTimeLabel}
<DetailField name="Performance">
VALUATION: 0{DEFAULT_FIAT} | PRICE: 0{DEFAULT_FIAT} | ROI: 0%
</DetailField>
{store.selectedPool.memo ? (
<DetailField name="Note">
{store.selectedPool.memo}
</DetailField>
) : null}
<DetailField name="Amount">
{store.selectedPool.amountLabel} {store.unitLabel}
<DetailField name="Pool">
CAP: 0{store.unitLabel} | FUNDED: 0% | INVESTORS: 1 | ID: {store.selectedPool.id}:BITS:dooca.net
</DetailField>
<DetailField name="Rewards">
{store.selectedPool.feeLabel} {store.unitLabel}
<DetailField name="Asset Supply">
TOTAL: 1,000 | CIRCULATING: 0 | ID: 234569876
</DetailField>
{store.selectedPool.confirmationsLabel ? (
<DetailField name="Confirmations">
{store.selectedPool.confirmationsLabel}
<DetailField name="Contract">
POOLERS: {store.selectedPool.confirmationsLabel} | CHAIN: {store.selectedPool.typeLabel}
</DetailField>
) : null}
<DetailField name="Status">
......
......@@ -179,8 +179,8 @@ const PoolView = ({ store, nav, pool, goPoolAdd }) => {
return (
<Background color={color.blackDark}>
<Header separator>
<ChannelButton onPress={() => nav.goURL('https://markets.bitsoko.org')} />
<Title title="Investment Fund" />
<ChannelButton onPress={() => nav.goInvestments()} />
<Title title="Investment Pools" />
<CancelButton onPress={() => nav.goHome()} />
</Header>
......
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { observer } from 'mobx-react';
import PropTypes from 'prop-types';
import Background from '../component/background';
import { Header, Title } from '../component/header';
import { CopyText } from '../component/text';
import { CopyButton, Button, BackButton, RadioButton } from '../component/button';
import { SettingContent, SettingList, SettingItem } from '../component/setting';
import { color, font } from '../component/style';
import { CopiedNotification, Alert } from '../component/notification';
import Text from '../component/text';
import LightningBoltIcon from '../../src/asset/icon/lightning-bolt';
import CopyDarkIcon from '../../src/asset/icon/copy-dark';
import BitcoinIcon from '../../src/asset/icon/bitcoin';
import Icon from '../component/icon';
//import ChartApp from './chart';
//
// Pool Summary
//
const summaryStyles = StyleSheet.create({
wrapper: {
flexDirection: 'row',
paddingBottom: 10,
paddingLeft: 50,
paddingRight: 50,
},
copyTxtX: {
textAlign: 'center',
marginTop: 35,
marginBottom: 25,
maxWidth: 450,
},
smlIcon: {
height: 24,
width: 24,
},
poolInfo: {
fontSize: 10,
lineHeight: 16,
textAlign: 'center',
width: '100%',
},
topIcon: {
height: 92,
width: 92,
marginLeft: 'calc( 50% - 46 )',
margin: 10,
marginRight: 3,
paddingTop: 50,
},
topPad: {
paddingTop: 50,
},
listIcon: {
height: 22,
width: 22,
justifyContent: 'left',
},
btnWrapper: {
flexDirection: 'row',
justifyContent: 'center',
},
box: {
flexDirection: 'row',
alignItems: 'center',
padding: 10,
marginRight: 20,
backgroundColor: color.glasDarker,
borderRadius: 5,
},
alert: {
marginRight: 10,
},
txt: {
fontSize: font.sizeXS,
lineHeight: font.lineHeightXS,
},
copyBtn: {
backgroundColor: color.glas,
marginBottom: 10,
},
total: {
marginLeft: 30,
},
});
const ContractSummary = ({
poolBalanceOpenLabel,
poolBalanceClosingLabel,
unitLabel,
}) => (
<View style={summaryStyles.wrapper}>
<View style={summaryStyles.box}>
<Alert type="success" style={summaryStyles.alert} />
<Text style={summaryStyles.txt}>Uptime</Text>
<Text style={[summaryStyles.txt, summaryStyles.total]}>
365 Days
</Text>
</View>
<View style={summaryStyles.box}>
<View style={summaryStyles.alert}>
<BitcoinIcon />
</View>
<Text style={summaryStyles.txt}> ID</Text>
<Text style={[summaryStyles.txt, summaryStyles.total]}>
1456789
</Text>
</View>
</View>
);
const ContractBalances = ({
balanceLabel,
unitLabel,
}) => (
<View style={summaryStyles.wrapper}>
<View style={summaryStyles.box}>
<View style={summaryStyles.alert}>
<LightningBoltIcon height={170 * 0.06} width={135 * 0.06} />
</View>
<Text style={summaryStyles.txt}>{balanceLabel}</Text>
<Text style={[summaryStyles.txt, summaryStyles.total]}>
{unitLabel}
</Text>
</View>
</View>
);
ContractSummary.propTypes = {
poolBalanceOpenLabel: PropTypes.string.isRequired,
poolBalanceClosingLabel: PropTypes.string.isRequired,
unitLabel: PropTypes.string,
};
ContractBalances.propTypes = {
balanceLabel: PropTypes.string.isRequired,
unitLabel: PropTypes.string,
};
//
// Setting Contract View
//
const SetContractView = ({ store, nav, setting, invoice }) => {
return (
<Background color={color.blackDark}>
<Header separator>
<BackButton onPress={() => nav.goSettings()} />
<Title title="Contract Settings" />
<Button disabled onPress={() => {}} />
</Header>
<Button style={summaryStyles.topBtn}>
<Icon
image={require('../asset/icon/algorand.png')}
style={summaryStyles.topIcon}
/>
<Title style={summaryStyles.poolInfo} title="Algorand" />
<Title style={summaryStyles.poolInfo} title="https://algorand.org" />
<CopyText style={summaryStyles.copyTxtX}>
A world where everyone creates and exchanges value efficiently, transparently, and securely.
</CopyText>
<ContractSummary style={summaryStyles.btnWrapper}
poolBalanceOpenLabel=""
poolBalanceClosingLabel=""
/>
<Title style={summaryStyles.poolInfo, summaryStyles.topPad} title="Account information" />
<ContractBalances style={summaryStyles.btnWrapper}
balanceLabel="Public"
unitLabel={store.settings.chains.algo.account.address}
/>
<View style={summaryStyles.box}>
<View style={summaryStyles.alert}>
<BitcoinIcon />
</View>
<Text style={summaryStyles.txt}> Balance</Text>
<Text style={[summaryStyles.txt, summaryStyles.total]}>
0.00001
</Text>
</View>
<ContractBalances style={summaryStyles.btnWrapper}
balanceLabel="Assets"
unitLabel="0"
/>
<CopyText style={summaryStyles.copyTxtX}>
Do not share this information or funds will be compromised
</CopyText>
<CopyButton
onPress={() => invoice.toClipboard({ text: store.settings.chains.algo.account.mnemonic })}
icon={<CopyDarkIcon height={17.5} width={14} />}
style={summaryStyles.copyBtn} >
private key
</CopyButton>
</Button>
<SettingContent>
<Title style={summaryStyles.poolInfo} title="How to connect" />
<SettingList>
<SettingItem
name="Remote"
label={store.settings.chains.algo.rpc[store.settings.chains.algo.chain].server}
onSelect={() => setting.contractConnection({ chain: 'algo', connect: 'remote' })}
>
<RadioButton selected={'local' != store.settings.chains.algo.chain} />
</SettingItem>
<SettingItem
name="Local"
onSelect={() => setting.contractConnection({ chain: 'algo', connect: 'local' })}
>
<RadioButton selected={'local' === store.settings.chains.algo.chain} />
</SettingItem>
</SettingList>
</SettingContent>
<CopiedNotification
display={store.displayCopied}
color={color.notifyLight}
/>
</Background>
);
};
SetContractView.propTypes = {
invoice: PropTypes.object.isRequired,
store: PropTypes.object.isRequired,
setting: PropTypes.object.isRequired,
nav: PropTypes.object.isRequired,
};
export default observer(SetContractView);
......@@ -10,7 +10,7 @@ import {
SettingItem,
SettingHeader,
} from '../component/setting';
import { CountBubble } from '../component/notification';
import { CountBubbleRed, CountBubbleGreen, CountBubbleOrange, CountBubbleGrey } from '../component/notification';
import { createStyles, maxWidth } from '../component/media-query';
import { color, breakWidth } from '../component/style';
......@@ -23,6 +23,7 @@ const baseStyles = {
justifyContent: 'flex-start',
alignItems: 'stretch',
paddingTop: 35,
paddingBottom: 35,
},
advanced: {
marginTop: 50,
......@@ -31,7 +32,6 @@ const baseStyles = {
const styles = createStyles(
baseStyles,
maxWidth(breakWidth, {
content: {
paddingTop: 35,
......@@ -54,7 +54,7 @@ const SettingView = ({ store, nav, wallet, autopilot, auth }) => {
onSelect={() => nav.goNotifications()}
arrow
>
<CountBubble>{store.notificationCountLabel}</CountBubble>
<CountBubbleRed>{store.notificationCountLabel}</CountBubbleRed>
</SettingItem>
<SettingItem
name="Bitcoin Unit"
......@@ -83,6 +83,28 @@ const SettingView = ({ store, nav, wallet, autopilot, auth }) => {
onValueChange={() => autopilot.toggle()}
/>
</SettingItem>
<SettingHeader name="CONTRACTS" style={styles.content}/>
<SettingItem
name="Algorand"
onSelect={() => nav.goContractSettings('algo')}
arrow
>
<CountBubbleOrange>testnet</CountBubbleOrange>
</SettingItem>
<SettingItem
name="Ethereum"
arrow
>
<CountBubbleGrey>offline</CountBubbleGrey>
<CountBubbleGreen>mainnet</CountBubbleGreen>
</SettingItem>
<SettingItem
name="Solana"
arrow
>
<CountBubbleGrey>offline</CountBubbleGrey>
<CountBubbleOrange>testnet</CountBubbleOrange>
</SettingItem>
<SettingHeader name="ADVANCED" style={styles.advanced} />
<SettingItem name="Logs" onSelect={() => nav.goCLI()} arrow />
</SettingContent>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment