diff --git a/examples/wallet/app/components/Listing/ListingColumn.js b/examples/wallet/app/components/Listing/ListingColumn.js
new file mode 100644
index 0000000..e0895e4
--- /dev/null
+++ b/examples/wallet/app/components/Listing/ListingColumn.js
@@ -0,0 +1,14 @@
+// @flow
+import React from 'react';
+import type { Node } from 'react';
+import Col from 'react-bootstrap/Col';
+
+type Props = {
+ children: Node
+};
+
+export default ({ children, ...other }: Props) => (
+
+ {children}
+
+);
diff --git a/examples/wallet/app/components/ListingRow.js b/examples/wallet/app/components/Listing/ListingRow.js
similarity index 58%
rename from examples/wallet/app/components/ListingRow.js
rename to examples/wallet/app/components/Listing/ListingRow.js
index 00531d8..08ee0ad 100644
--- a/examples/wallet/app/components/ListingRow.js
+++ b/examples/wallet/app/components/Listing/ListingRow.js
@@ -5,13 +5,13 @@ import Row from 'react-bootstrap/Row';
import styles from './ListingRow.scss';
type Props = {
- key: string | number,
+ itemKey: string | number,
className?: string,
children: Node
};
-export default ({ key, className, children }: Props) => (
-
+export default ({ itemKey, className, children }: Props) => (
+
{children}
);
diff --git a/examples/wallet/app/components/ListingRow.scss b/examples/wallet/app/components/Listing/ListingRow.scss
similarity index 100%
rename from examples/wallet/app/components/ListingRow.scss
rename to examples/wallet/app/components/Listing/ListingRow.scss
diff --git a/examples/wallet/app/components/Listing/ListingTable.js b/examples/wallet/app/components/Listing/ListingTable.js
new file mode 100644
index 0000000..21a3db8
--- /dev/null
+++ b/examples/wallet/app/components/Listing/ListingTable.js
@@ -0,0 +1,14 @@
+// @flow
+import React from 'react';
+import type { Node } from 'react';
+import Container from 'react-bootstrap/Container';
+
+type Props = {
+ children: Node
+};
+
+export default ({ children, ...other }: Props) => (
+
+ {children}
+
+);
diff --git a/examples/wallet/app/components/OwnStakepoolsList.js b/examples/wallet/app/components/OwnStakepoolsList.js
new file mode 100644
index 0000000..b6e564e
--- /dev/null
+++ b/examples/wallet/app/components/OwnStakepoolsList.js
@@ -0,0 +1,29 @@
+// @flow
+import React from 'react';
+import Button from 'react-bootstrap/Button';
+import ListingColumn from './Listing/ListingColumn';
+import ListingTable from './Listing/ListingTable';
+import type { PoolId } from '../models';
+import ListingRow from './Listing/ListingRow';
+
+type Props = {
+ stakePools: Array
+};
+
+export default ({ stakePools }: Props) => {
+ return (
+
+ {stakePools &&
+ stakePools.map((poolId: PoolId) => {
+ return (
+
+ {poolId}
+
+
+
+
+ );
+ })}
+
+ );
+};
diff --git a/examples/wallet/app/components/StakePoolList.js b/examples/wallet/app/components/StakePoolList.js
index 814d3e1..41a5cf5 100644
--- a/examples/wallet/app/components/StakePoolList.js
+++ b/examples/wallet/app/components/StakePoolList.js
@@ -1,13 +1,13 @@
// @flow
import React from 'react';
import Button from 'react-bootstrap/Button';
-import Col from 'react-bootstrap/Col';
import Row from 'react-bootstrap/Row';
-import Container from 'react-bootstrap/Container';
+import ListingColumn from './Listing/ListingColumn';
+import ListingTable from './Listing/ListingTable';
import type { NewDelegation, PoolId, Delegation } from '../models';
import type { PoolSelectionHandler } from './StakeDelegation';
import { percentageFromParts } from '../utils/proportionsHelper';
-import ListingRow from './ListingRow';
+import ListingRow from './Listing/ListingRow';
import styles from './StakePoolList.scss';
type Props = {
@@ -24,7 +24,7 @@ export default ({
newDelegation
}: Props) => {
return (
-
+
{stakePools &&
stakePools.map((poolId: PoolId) => {
const activeDelegation = newDelegation[poolId];
@@ -36,15 +36,17 @@ export default ({
const currentDelegationPercentage =
currentDelegation && percentageFromParts(currentDelegation, poolId);
return (
-
-
+
+
{poolId}
-
-
+
+
{newDelegationPercentage}%
-
- {currentDelegationPercentage}%
-
+
+
+ {currentDelegationPercentage}%
+
+
-
+
);
})}
-
+
);
};
diff --git a/examples/wallet/app/components/TransactionListing.js b/examples/wallet/app/components/TransactionListing.js
index d316233..c62fc31 100644
--- a/examples/wallet/app/components/TransactionListing.js
+++ b/examples/wallet/app/components/TransactionListing.js
@@ -1,12 +1,11 @@
// @flow
import React from 'react';
-import Col from 'react-bootstrap/Col';
-import Container from 'react-bootstrap/Container';
import curry from 'lodash/curry';
import ClickableBox from 'clickable-box';
import config from 'config';
// FIXME: this is obviously not portable to a webapp
import { shell } from 'electron';
+import ListingTable from './Listing/ListingTable';
import type {
Transaction,
Address,
@@ -14,7 +13,8 @@ import type {
TransactionOutput
} from '../models';
import styles from './TransactionListing.scss';
-import ListingRow from './ListingRow';
+import ListingRow from './Listing/ListingRow';
+import ListingColumn from './Listing/ListingColumn';
type Props = {
transactions: Array,
@@ -23,9 +23,9 @@ type Props = {
export default ({ transactions, myAddress }: Props) => {
return (
-
+
{transactions.map(curry(transactionToRow)(myAddress))}
-
+
);
};
@@ -55,11 +55,11 @@ const transactionToRow = (
return null;
}
return (
-
-
+
+
{transactionType}
-
-
+
+
shell.openExternal(
@@ -71,16 +71,16 @@ const transactionToRow = (
>
{id}
-
+
{/* TODO show date */}
- 04/20/2020
-
+ 04/20/2020
+
{inputSum > outputSum ? inputSum : outputSum}
-
+
{/* TODO show confirmations */}
-
+
pending
-
+
{/* TODO add a dropdown with details (inpt sum, output sum, ) */}
);
diff --git a/examples/wallet/app/containers/OwnStakepoolsList.js b/examples/wallet/app/containers/OwnStakepoolsList.js
new file mode 100644
index 0000000..4bf8fb7
--- /dev/null
+++ b/examples/wallet/app/containers/OwnStakepoolsList.js
@@ -0,0 +1,28 @@
+// @flow
+import { connect } from 'react-redux';
+import type { AppState } from '../reducers/types';
+import type { Pool, PoolId } from '../models';
+import OwnStakepoolsList from '../components/OwnStakepoolsList';
+
+export type GetOnlyOwnStakepools = typeof getOnlyOwnStakepools;
+
+export function getOnlyOwnStakepools(
+ state: AppState
+): { stakePools: Array } {
+ const {
+ stakePools: { availablePools },
+ account: { publicKey }
+ } = state;
+ console.log(availablePools);
+ return {
+ stakePools: availablePools
+ .filter(
+ (pool: Pool) =>
+ pool.owners.find(it => it === publicKey) ||
+ pool.operators.find(it => it === publicKey)
+ )
+ .map(({ id }) => id)
+ };
+}
+
+export default connect(getOnlyOwnStakepools)(OwnStakepoolsList);
diff --git a/examples/wallet/app/pages/OwnStakepools.js b/examples/wallet/app/pages/OwnStakepools.js
index af8a444..7e026ac 100644
--- a/examples/wallet/app/pages/OwnStakepools.js
+++ b/examples/wallet/app/pages/OwnStakepools.js
@@ -3,6 +3,7 @@ import React from 'react';
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import SidebarLayout from '../containers/SidebarLayout';
+import OwnStakepoolsList from '../containers/OwnStakepoolsList';
export default () => (
@@ -10,6 +11,7 @@ export default () => (
My stakepools
+
);
diff --git a/examples/wallet/app/reducers/types.js b/examples/wallet/app/reducers/types.js
index fc0d2e1..95daada 100644
--- a/examples/wallet/app/reducers/types.js
+++ b/examples/wallet/app/reducers/types.js
@@ -6,6 +6,7 @@ import type {
Balance,
Counter,
PrivateKey,
+ PublicKey,
Delegation,
Identifier,
Pool,
@@ -34,6 +35,7 @@ export type Account = AccountKeys &
export type AccountKeys = {
address: Address,
privateKey: PrivateKey,
+ publicKey: PublicKey,
identifier: Identifier
};
diff --git a/examples/wallet/app/utils/wasmWrapper.js b/examples/wallet/app/utils/wasmWrapper.js
index 08acb04..86c579e 100644
--- a/examples/wallet/app/utils/wasmWrapper.js
+++ b/examples/wallet/app/utils/wasmWrapper.js
@@ -52,6 +52,7 @@ async function getAccountDataFromPrivateKey(
.to_string(config.get('addressPrefix'));
return {
address,
+ publicKey: publicKey.to_bech32(),
privateKey: secret,
identifier: identifier.to_hex()
};
diff --git a/examples/wallet/test/containers/OwnStakepoolsList.spec.js b/examples/wallet/test/containers/OwnStakepoolsList.spec.js
new file mode 100644
index 0000000..11d3222
--- /dev/null
+++ b/examples/wallet/test/containers/OwnStakepoolsList.spec.js
@@ -0,0 +1,129 @@
+// @flow
+import type { Pool } from '../../app/models';
+import type { AppState } from '../../app/reducers/types';
+import { getOnlyOwnStakepools } from '../../app/containers/OwnStakepoolsList';
+
+describe('OwnStakePoolsContainer getOnlyOwnStakepools', () => {
+ const publicKey = 'publicKey';
+ const createState = (pools: Array): AppState => ({
+ stakePools: { availablePools: pools },
+ account: { publicKey }
+ });
+
+ describe('GIVEN a state without any stakepools', () => {
+ let state;
+ beforeAll(() => {
+ state = createState([]);
+ });
+ describe('WHEN getting the users own stakepools', () => {
+ let stakePools;
+ beforeAll(() => {
+ ({ stakePools } = getOnlyOwnStakepools(state));
+ });
+ test('THEN the user has no stakepools', () => {
+ expect(stakePools).toBeInstanceOf(Array);
+ expect(stakePools).toHaveLength(0);
+ });
+ });
+ });
+
+ describe('GIVEN a state with many stakepools, but none administered by the user', () => {
+ let state;
+ beforeAll(() => {
+ state = createState([
+ { id: '1', owners: ['someoneelse'], operators: ['anotheruser'] },
+ { id: '2', owners: [], operators: ['anotheruser', 'someoneelse'] },
+ { id: '3', owners: ['someoneelse', 'anotheruser'], operators: [] }
+ ]);
+ });
+ describe('WHEN getting the users own stakepools', () => {
+ let stakePools;
+ beforeAll(() => {
+ ({ stakePools } = getOnlyOwnStakepools(state));
+ });
+ test('THEN the user has no stakepools', () => {
+ expect(stakePools).toBeInstanceOf(Array);
+ expect(stakePools).toHaveLength(0);
+ });
+ });
+ });
+
+ describe('GIVEN a state with many stakepools, but none administered by the user', () => {
+ let state;
+ beforeAll(() => {
+ state = createState([
+ { id: '1', owners: ['someoneelse'], operators: ['anotheruser'] },
+ { id: '2', owners: [], operators: ['anotheruser', 'someoneelse'] },
+ { id: '3', owners: ['someoneelse', 'anotheruser'], operators: [] }
+ ]);
+ });
+ describe('WHEN getting the users own stakepools', () => {
+ let stakePools;
+ beforeAll(() => {
+ ({ stakePools } = getOnlyOwnStakepools(state));
+ });
+ test('THEN the user has no stakepools', () => {
+ expect(stakePools).toBeInstanceOf(Array);
+ expect(stakePools).toHaveLength(0);
+ });
+ });
+ });
+
+ describe('GIVEN a state with one stakepool, owned by only the user', () => {
+ let state;
+ beforeAll(() => {
+ state = createState([{ id: '1', owners: [publicKey], operators: [] }]);
+ });
+ describe('WHEN getting the users own stakepools', () => {
+ let stakePools;
+ beforeAll(() => {
+ ({ stakePools } = getOnlyOwnStakepools(state));
+ });
+ test('THEN the user has only one stakepool', () => {
+ expect(stakePools).toBeInstanceOf(Array);
+ expect(stakePools).toHaveLength(1);
+ expect(stakePools[0]).toBe('1');
+ });
+ });
+ });
+
+ describe('GIVEN a state with one stakepool, administered and owned by the user', () => {
+ let state;
+ beforeAll(() => {
+ state = createState([
+ { id: '1', owners: [publicKey], operators: [publicKey] }
+ ]);
+ });
+ describe('WHEN getting the users own stakepools', () => {
+ let stakePools;
+ beforeAll(() => {
+ ({ stakePools } = getOnlyOwnStakepools(state));
+ });
+ test('THEN the user has only one stakepool', () => {
+ expect(stakePools).toBeInstanceOf(Array);
+ expect(stakePools).toHaveLength(1);
+ expect(stakePools[0]).toBe('1');
+ });
+ });
+ });
+
+ describe('GIVEN a state with one stakepool, administered by the user and owned by someone else', () => {
+ let state;
+ beforeAll(() => {
+ state = createState([
+ { id: '1', owners: ['someoneelse'], operators: [publicKey] }
+ ]);
+ });
+ describe('WHEN getting the users own stakepools', () => {
+ let stakePools;
+ beforeAll(() => {
+ ({ stakePools } = getOnlyOwnStakepools(state));
+ });
+ test('THEN the user has only one stakepool', () => {
+ expect(stakePools).toBeInstanceOf(Array);
+ expect(stakePools).toHaveLength(1);
+ expect(stakePools[0]).toBe('1');
+ });
+ });
+ });
+});