Skip to content

Commit

Permalink
Merge pull request #45 from etclabscore/feat/add-list-account-caveats
Browse files Browse the repository at this point in the history
feat: add list account caveats
  • Loading branch information
shanejonas authored Oct 1, 2020
2 parents ea02527 + 8850db8 commit c1bad16
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 11 deletions.
24 changes: 24 additions & 0 deletions src/components/AccountSelectList.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from "react";
import ReactDOM from "react-dom";
import AccountSelectList from "./AccountSelectList";

describe("AccountSelectList", () => {
it("can render without crashing", () => {
const div = document.createElement("div");
ReactDOM.render(<AccountSelectList accounts={[]}/>, div);
ReactDOM.unmountComponentAtNode(div);
});
it("can render accounts", () => {
const div = document.createElement("div");
ReactDOM.render(<AccountSelectList accounts={[
{
address: "0x123",
name: "potato",
hidden: false,
},
]}/>, div);
expect(div.innerHTML).toContain("0x123");
expect(div.innerHTML).toContain("potato");
ReactDOM.unmountComponentAtNode(div);
});
});
51 changes: 51 additions & 0 deletions src/components/AccountSelectList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { useState } from "react";
import { List, ListItem, ListItemText, ListItemSecondaryAction, Checkbox, Typography } from "@material-ui/core";
import { Account } from "@etclabscore/signatory-core";

interface IProps {
accounts: Account[];
onChange?: (checked: Account[]) => void;
}

const AccountSelectList: React.FC<IProps> = (props) => {
const [checked, setChecked] = useState<Account[]>([]);

const handleToggle = (value: Account) => () => {
const currentIndex = checked.indexOf(value);
const newChecked = [...checked];

if (currentIndex === -1) {
newChecked.push(value);
} else {
newChecked.splice(currentIndex, 1);
}

setChecked(newChecked);
if (props.onChange) {
props.onChange(newChecked);
}
};
return (
<List>
{props.accounts.map((account) => {
return (
<ListItem onClick={handleToggle(account)} button>
<ListItemText primary={
<Typography variant="caption" style={{ fontSize: "9px" }}>
{account.address}
</Typography>
} secondary={account.name}></ListItemText>
<ListItemSecondaryAction>
<Checkbox
onChange={handleToggle(account)}
checked={checked.indexOf(account) !== -1}
/>
</ListItemSecondaryAction>
</ListItem>
);
})}
</List>
);
};

export default AccountSelectList;
2 changes: 1 addition & 1 deletion src/components/HexToNumberConverter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface IProps {
}

const HexToNumberConverter: React.FC<IProps> = (props) => {
const [state, send, machine] = useMachine(hexToNumberMachine.withContext({ hex: props.value, number: "" }));
const [state, send, machine] = useMachine(hexToNumberMachine.withContext({ hex: props.value, number: "" }), { devtools: true });
machine.onChange((context: any) => {
if (props.onChange) {
props.onChange(context.hex);
Expand Down
2 changes: 1 addition & 1 deletion src/components/HexToString.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface IProps {
}

const HexToStringConverter: React.FC<IProps> = (props) => {
const [state, send, machine] = useMachine(hexToStringMachine.withContext({ hex: props.value, string: "" }));
const [state, send, machine] = useMachine(hexToStringMachine.withContext({ hex: props.value, string: "" }), { devTools: true });
machine.onChange((context: any) => {
if (props.onChange) {
props.onChange(context.hex);
Expand Down
13 changes: 9 additions & 4 deletions src/containers/MyApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import PasswordWidget from "../components/PasswordWidget";
import InfoDialog from "../components/InfoDialog";
import { capabilities } from "../capabilities";
import { RpcCapDomainEntry } from "@xops.net/rpc-cap";
import AccountSelectList from "../components/AccountSelectList";
import { Account } from "@etclabscore/signatory-core";

export const matchesMachineState = (
states: string[],
Expand Down Expand Up @@ -93,6 +95,7 @@ const MyApp = () => {
});
pmServer.start();
setJsonrpcServer(pmServer);

// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

Expand Down Expand Up @@ -532,16 +535,18 @@ const MyApp = () => {
{state.context.formData && state.context.formData.permissions &&
_.map(state.context.formData.permissions, (value, key) => {
return (
<Grid container direction="row">
<Grid container direction="column">
<FormControlLabel
control={<Checkbox checked={true} name={key} />}
label={`Trust this app to [${key}]?`}
/>
{/* {key === "listAccounts" &&
{key === "listAccounts" &&
<>
<SelectAccount accounts={state.context.cards} />
<br />
<Typography>Select account(s)</Typography>
<AccountSelectList accounts={state.context.cards} onChange={(accounts: Account[]) => send("ACCOUNTS_CHANGED", { accounts })} />
</>
} */}
}
</Grid>
);
})
Expand Down
42 changes: 42 additions & 0 deletions src/machines/appMachine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import { methods as signatoryFactory } from "@etclabscore/signatory-core/build/s
import accountsToTree from "../helpers/accountsToTree";
import SignatoryLocalStorage from "../storage/signatoryLocalStorage";
import saveJSON from "../helpers/saveJSON";
import { IOcapLdCaveat } from "@xops.net/rpc-cap";
import _ from "lodash";

const signatoryCore = signatoryFactory(new SignatoryLocalStorage());

export interface ICard {
name?: string;
parent?: string;
description?: string;
hidden?: boolean;
uuid?: string;
address?: string;
ref?: Interpreter<any>;
Expand All @@ -29,6 +32,7 @@ export interface IContext {
error: null | Error;
result: null | string;
createData: null | IFormData;
caveats?: IOcapLdCaveat;
invokePromiseSuccess?: undefined | InvokePromiseSuccessReject;
invokePromiseReject?: undefined | InvokePromiseSuccessReject;
}
Expand Down Expand Up @@ -271,8 +275,40 @@ export const rawAppMachine: any = {
requestPermissions: {
on: {
CANCEL: "cancelling",
ACCOUNTS_CHANGED: {
actions: assign({
caveats: (context: any, event: any) => {
const filtered = context.cards.filter((card: any) => {
return event.accounts.includes(card);
});
if (filtered.length === 0) {
return;
}
return {
name: "filteredAccounts",
type: "filterResponse",
value: filtered.map((value: ICard) => {
return _.omitBy({
address: value.address,
name: value.name,
hidden: value.hidden,
description: value.description,
parent: value.parent,
}, _.isUndefined);
}),
};
},
}),
},
SUBMIT: {
target: "success",
cond: (context: IContext, event: any) => {
if (context.caveats) {
return context.caveats;
} else {
return false;
}
},
actions: assign({
result: (context, event: any) => {
return "Granted Permissions";
Expand Down Expand Up @@ -448,6 +484,9 @@ export const rawAppMachine: any = {
invokePromiseReject: () => {
return undefined;
},
caveats: () => {
return undefined;
},
}),
},
},
Expand All @@ -471,6 +510,9 @@ export const rawAppMachine: any = {
invokePromiseReject: () => {
return undefined;
},
caveats: () => {
return undefined;
},
}),
},
},
Expand Down
4 changes: 3 additions & 1 deletion src/postMessageServer/methods/methodMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { IContext } from "../../machines/appMachine";
import { IPostMessageServerOptions } from "../postMessageServer";
import { methods as signatoryFactory } from "@etclabscore/signatory-core/build/src/index";
import SignatoryLocalStorage from "../../storage/signatoryLocalStorage";
import _ from "lodash";
export interface IMethodMapping {
[methodName: string]: (...params: any) => Promise<any>;
}
Expand All @@ -23,7 +24,8 @@ type TGenerateMethodMapping = (options: IPostMessageServerOptions) => IMethodMap
const generateMethodMapping: TGenerateMethodMapping = (options) => {

const listAccounts: ListAccounts = async () => {
return signatoryCore.listAccounts();
const r = await signatoryCore.listAccounts();
return r.map((item) => _.omitBy(item, _.isUndefined)) as any;
};

const sign: any = async (dataToSign: Data, address: Address, chainId: ChainId, domain: any) => {
Expand Down
17 changes: 15 additions & 2 deletions src/postMessageServer/postMessageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,23 @@ const generatePermissions = (
options.send("REQUEST_PERMISSIONS", {
approvalRequest,
invokePromiseSuccess: async (context: IContext, event: any, data: any) => {
resolve(approvalRequest.permissions);
let permissions = {
listAccounts: {
...approvalRequest.permissions.listAccounts,
},
};
if (context.caveats) {
permissions = {
listAccounts: {
...approvalRequest.permissions.listAccounts,
caveats: [context.caveats],
},
};
}
resolve(permissions);
},
invokePromiseReject: async (context: IContext, event: any, error: any) => {
reject(error);
reject(new Error("User Rejected Request"));
},
});
});
Expand Down
7 changes: 5 additions & 2 deletions src/storage/signatoryLocalStorage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Storage, AccountStorageData, AccountMetadata } from "@etclabscore/signatory-core/build/src/lib/storage";
import { WalletType, DeterministicWallet, NonDeterministicWallet } from "@etclabscore/signatory-core/build/src/lib/wallet";
import * as ethUtil from "ethereumjs-util";
import _ from "lodash";

export class SignatoryLocalStorage implements Storage {
public storage: any;
Expand Down Expand Up @@ -50,10 +51,12 @@ export class SignatoryLocalStorage implements Storage {
switch (wallet.type) {
case "non-deterministic":
const { address, parent } = wallet;
return { address, parent, name, description, type: wallet.type, hidden: !visible };
return _.omitBy<AccountMetadata>({
address, parent, name, description, type: wallet.type, hidden: !visible,
}, _.isUndefined);
case "deterministic":
const { uuid, hdPath } = wallet;
return { uuid, name, description, hdPath, type: wallet.type, hidden: !visible };
return { uuid, name, description, hdPath, type: wallet.type, hidden: !visible } as any;
}
return wallet;
}));
Expand Down

0 comments on commit c1bad16

Please sign in to comment.