Skip to content

Commit

Permalink
feat(wallet-connection): create new cross-framework UI
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed Sep 25, 2021
1 parent 05e4370 commit 905bf6c
Show file tree
Hide file tree
Showing 19 changed files with 2,693 additions and 76 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
"packages/xsnap",
"packages/deploy-script-support",
"packages/ui-components",
"packages/eslint-config"
"packages/eslint-config",
"packages/wallet-connection"
],
"devDependencies": {
"@endo/eslint-config": "^0.3.9",
Expand Down
29 changes: 29 additions & 0 deletions packages/wallet-connection/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org

root = true


[*]

# Change these settings to your own preference
indent_style = space
indent_size = 2

# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[*.json]
indent_size = 2

[*.{html,js,md}]
block_comment_start = /**
block_comment = *
block_comment_end = */
24 changes: 24 additions & 0 deletions packages/wallet-connection/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## editors
/.idea
/.vscode

## system files
.DS_Store

## npm
/node_modules/
/npm-debug.log

## testing
/coverage/

## temp folders
/.tmp/

# build
/_site/
/dist/
/out-tsc/

storybook-static
custom-elements.json
21 changes: 21 additions & 0 deletions packages/wallet-connection/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2021 agoric-wallet-connection

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
185 changes: 185 additions & 0 deletions packages/wallet-connection/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# \<agoric-wallet-connection>

This webcomponent follows the [open-wc](https://github.com/open-wc/open-wc)
recommendations.

## Installation

```bash
yarn add @agoric/wallet-connection ses @agoric/eventual-send
```

## Usage

This component works with modern browsers using any framework that supports
standard Web Components. The only popular framework that needs additional help
to use Web Components is ReactJS, for which we provide a [React-specific wrapper](#ReactJS).

### Setup

You will need to ensure your app first installs and locks down the JS
environment using
[SES](https://github.com/endojs/endo/tree/master/packages/ses#readme).

You can create an `install-ses-lockdown.js` module that does all the setup
needed by your app:

```js
/* global lockdown */
import 'ses'; // adds lockdown, harden, and Compartment
import '@agoric/eventual-send/shim.js'; // adds support needed by E

// Help lock down the JS environment. The start compartment (current evaluation context)
// can still access powerful globals, but this start compartment can use `new Compartment(...)`
// to evaluate code with stricter confinement.
lockdown({
errorTaming: 'unsafe',
overrideTaming: 'severe',
});

Error.stackTraceLimit = Infinity;
```

In all apps, you will need to import the above file to enable the RPC
environment that `agoric-wallet-connection` uses:

```js
// Ensure this is imported before anything else in your project.
import './install-ses-lockdown.js';
```

Somewhere else, you will need to define custom event handlers:

```js
import { E } from '@agoric/eventual-send';

// This will possibly run multiple times whenever `.connecting` is set.
const onOpen = ev => {
// You should reconstruct all state here, given that the wallet is only now freshly open.
console.log('Agoric wallet connected');

// This is one of the only methods that the wallet facet allows.
/** @type {ERef<WalletBridge>} */
const walletBridge = E(ev.wallet).getScopedBridge('My dapp', window.location.origin);
// Now use the WalletBridge as desired.
const zoe = E(walletBridge).getZoe();
// ...
};

// This will run for every notable error, maybe multiple times per wallet connection.
const onError = ev => {
console.error('Agoric wallet got connection error', ev.message);
};

// This will run every time the wallet connection closes, including if the
// latest connection attempt has failed to open.
// If `.connecting` is still set after this callback, then the connection will retry.
const onClose = ev => {
// Clean up app state since the wallet connection is closed.
console.log('Agoric wallet closed', ev.code, ev.reason);
};
```

### Vanilla JS

This is an example of how to use the wallet connection in plain HTML:

```html
<agoric-wallet-connection></agoric-wallet-connection>

<button>Connect to Wallet</button>

<script type="module">
import './install-ses-lockdown.js';
import '@agoric/wallet-connection/agoric-wallet-connection.js';
// Set up event handlers.
const awc = document.querySelector('agoric-wallet-connection');
awc.addEventListener('open', onOpen);
awc.addEventListener('error', onError);
awc.addEventListener('close', onClose);
// Configure the listener.
document.querySelector('button').addEventListener(ev => {
// Start the wallet connection.
// Will retry until `.connecting` is explicitly set to `false`.
awc.connecting = true;
});
</script>
```

### ReactJS

This is an example of how to use the wallet connection from
[React](https://reactjs.org).

```js
import React, { useCallback } from 'react';
import { makeReactAgoricWalletConnection } from '@agoric/wallet-connection/react.js';

// Create a wrapper for agoric-wallet-connection that is specific to
// the app's instance of React.
const AgoricWalletConnection = makeReactAgoricWalletConnection(React);

const MyWalletConnection = ({ connecting }) => {
const onOpen = useCallback(ev => { /* use ev.wallet */ }, []);
const onClose = useCallback(ev => { /* use ev.code, ev.reason */ }, []);
const onError = useCallback(ev => { /* use ev.message */ }, []);
return (
<AgoricWalletConnection
connecting={connecting}
onOpen={onOpen}
onClose={onClose}
onError={onError}
/>
);
}
```

### Other frameworks

Please look up documentation on how to use your framework with Web Components.
If you have a working example of how to do so, please consider submitting a PR
against this README.md to help others learn.

## Linting and formatting

To scan the package for linting and formatting errors, run

```bash
yarn lint
```

To automatically fix linting and formatting errors, run

```bash
yarn format
```

## Testing with Web Test Runner

To execute a single test run:

```bash
yarn test
```

To run the tests in interactive watch mode run:

```bash
yarn test:watch
```


## Tooling configs

For most of the tools, the configuration is in the `package.json` to minimize
the amount of files in this package.

## Local Demo with `web-dev-server`

```bash
yarn start
```

To run a local development server that serves the basic demo located in `demo/index.html`
3 changes: 3 additions & 0 deletions packages/wallet-connection/agoric-wallet-connection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { AgoricWalletConnection } from './src/AgoricWalletConnection.js';

window.customElements.define('agoric-wallet-connection', AgoricWalletConnection);
55 changes: 55 additions & 0 deletions packages/wallet-connection/connectionMachine.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Machine({
id: 'Agoric Wallet Connection',
initial: 'idle',
context: {
location: null,
connecting: false,
},
states: {
idle: {
on: {
'': {
target: 'locating',
cond: 'connecting',
},
},
},
locating: {
'': {
target: 'bridging',
cond: 'hasLocation',
},
},
bridging: {
BRIDGED: {
target: 'connected',
cond: 'connecting',
},
},
connected: {
},
waitToRetry: {
TICK: 'locating',
},
},
on: {
'': {
target: 'idle',
cond: 'notConnecting',
},
'DISCONNECT': 'waitToRetry',
'UPDATE.LOCATION': {
target: 'bridging',
actions: assign({
location: (_, event) => event.value,
}),
cond: 'locationChanged',
},
},
guards: {
locationChanged: (context, event) => context.location !== event.value,
hasLocation: (context) => context.location !== null,
notConnecting: context => !context.connecting,
connecting: context => context.connecting,
},
})
32 changes: 32 additions & 0 deletions packages/wallet-connection/demo/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!doctype html>
<html lang="en-GB">
<head>
<meta charset="utf-8">
<style>
body {
background: #fafafa;
}
</style>
</head>
<body>
<div id="demo"></div>

<script type="module">
import { html, render } from 'lit';
import '../agoric-wallet-connection.js';

const onOpen = ev => {
console.log('connected', ev);
const walletBridge = E(ev.wallet).getScopedBridge('Example Dapp', window.location.origin);
const zoe = E(walletBridge).getZoe();
console.log(zoe);
};
render(
html`
<agoric-wallet-connection @open=${onOpen} connecting></agoric-wallet-connection>
`,
document.querySelector('#demo')
);
</script>
</body>
</html>
1 change: 1 addition & 0 deletions packages/wallet-connection/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { AgoricWalletConnection } from './src/AgoricWalletConnection.js';
Loading

0 comments on commit 905bf6c

Please sign in to comment.