@@ -0,0 +1,226 @@
1+import { Just, Nothing } from 'folktale/maybe'
2+import React from 'react'
3+import { pour } from 'sigil-js'
4+import * as ob from 'urbit-ob'
5+import * as azimuth from 'azimuth-js'
7+import { addressFromSecp256k1Public, EthereumWallet } from '../lib/wallet'
8+import { ROUTE_NAMES } from '../lib/router'
10+import PointList from '../components/PointList'
11+import ReactSVGComponents from '../components/ReactSVGComponents'
12+import KeysAndMetadata from './Point/KeysAndMetadata'
13+import Actions from './Point/Actions'
14+import { BRIDGE_ERROR } from '../lib/error'
15+import { Row, Col, Warning, Button, H1, H3 } from '../components/Base'
17+// for wallet generation
18+import * as wg from '../../walletgen/lib/lib'
19+import PaperCollateralRenderer from 'PaperCollateralRenderer'
20+import JSZip from 'jszip'
21+import saveAs from 'file-saver'
23+class InviteWallet extends React.Component {
36+ this.download = this.download.bind(this)
37+ this.proceed = this.proceed.bind(this)
40+ componentDidMount() {
41+ const { web3, wallet, contracts, setPointCursor } = this.props
44+ contracts.chain(ctrcs =>
45+ wallet.chain(async wal => {
46+ const addr = addressFromSecp256k1Public(wal.publicKey);
47+ console.log('fetching incoming for', addr)
48+ const incoming = await azimuth.azimuth.getTransferringFor(ctrcs, addr)
49+ console.log('incoming', incoming)
51+ let point = Nothing();
52+ if (incoming.length > 0) {
53+ let pointNum = parseInt(incoming[0]);
54+ point = Just(pointNum);
55+ this.generateWallet(pointNum);
56+ if (incoming.length > 1) {
57+ //TODO notify user "...and others / ticket reusable"
60+ this.setState({loaded: true, point: point})
64+ componentDidUpdate(prevProps) {
68+ async generateWallet(point) {
69+ const ticket = await wg.makeTicket(point);
70+ const wallet = await wg.generateWallet(point, ticket);
71+ this.setState({ wallet: Just(wallet) });
75+ const zip = new JSZip();
76+ //TODO the categories here aren't explained in bridge at all...
78+ const bin0 = this.state.paper.filter(item => item.bin === '0');
79+ const bin1 = this.state.paper.filter(item => item.bin === '1');
80+ const bin2 = this.state.paper.filter(item => item.bin === '2');
81+ const bin3 = this.state.paper.filter(item => item.bin === '3');
82+ const bin4 = this.state.paper.filter(item => item.bin === '4');
84+ const bin0Folder = zip.folder("0. Public");
85+ const bin1Folder = zip.folder("1. Very High Friction Custody");
86+ const bin2Folder = zip.folder("2. High Friction Custody");
87+ const bin3Folder = zip.folder("3. Medium Friction Custody");
88+ const bin4Folder = zip.folder("4. Low Friction Custody");
90+ bin0.forEach(item => bin0Folder.file(`${item.pageTitle}.png`, item.png))
91+ bin1.forEach(item => bin1Folder.file(`${item.pageTitle}.png`, item.png));
92+ bin2.forEach(item => bin2Folder.file(`${item.pageTitle}.png`, item.png));
93+ bin3.forEach(item => bin3Folder.file(`${item.pageTitle}.png`, item.png));
94+ bin4.forEach(item => bin4Folder.file(`${item.pageTitle}.png`, item.png));
96+ zip.generateAsync({type:"blob"}).then((content) => {
97+ saveAs(content, 'urbit-wallet.zip');
98+ this.setState({ downloaded: true });
103+ this.props.pushRoute(ROUTE_NAMES.INVITE_VERIFY, {
104+ ticket: this.state.wallet.value.ticket,
105+ point: parseInt(this.state.point.value)
111+ const { loaded, point, wallet, paper, downloaded } = this.state;
115+ loading = ( <div>{ 'Loading...' }</div> );
119+ if (loaded && Nothing.hasInstance(point)) {
122+ <h3 className={'mb-2'}>{'Warning'}</h3>
124+ 'This invite has no claimable balance.'
131+ if (loaded && Just.hasInstance(point)) {
132+ const name = ob.patp(point.value);
133+ const sigil = pour({
135+ renderer: ReactSVGComponents,
139+ //TODO Passport display component
141+ <div className={'mt-12 pt-6'}>
144+ <H3><code>{ name }</code></H3>
149+ let downloadButtonContents = 'Download wallet';
150+ if ( Nothing.hasInstance(this.state.wallet) ||
151+ Nothing.hasInstance(this.state.paper) ) {
152+ downloadButtonContents = (
154+ <span className="btn-spinner"></span>
155+ {'Generating wallet...'}
166+ prop-size={'lg wide'}
167+ disabled={( Nothing.hasInstance(this.state.wallet) ||
168+ Nothing.hasInstance(this.state.paper) )}
169+ onClick={this.download}
171+ <span className="relative">
172+ { downloadButtonContents }
180+ prop-size={'lg wide'}
181+ disabled={!this.state.downloaded}
182+ onClick={this.proceed}
190+ if ( Just.hasInstance(this.state.wallet) &&
191+ Nothing.hasInstance(this.state.paper) ) {
192+ console.log('rendering for', point.value)
194+ <PaperCollateralRenderer
195+ wallet={{[point.value]: wallet.value}}
196+ className={'extremely-hidden'}
198+ console.log('got paper', data);
199+ this.setState({isRendering: false, paper: data})
201+ mode={'REGISTRATION'} />
213+ <p>{'TODO copy. you need a wallet to receive the point into. download it below. also explanation of wallet files/storage'}</p>
226+export default InviteWallet