@@ -0,0 +1,222 @@
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'
9+ addressFromSecp256k1Public,
10+ urbitWalletFromTicket,
13+} from '../lib/wallet'
15+import ReactSVGComponents from '../components/ReactSVGComponents'
16+import KeysAndMetadata from './Point/KeysAndMetadata'
17+import Actions from './Point/Actions'
18+import { BRIDGE_ERROR } from '../lib/error'
19+import { Row, Col, Warning, Button, H1, H3 } from '../components/Base'
20+import StatelessTransaction from '../components/StatelessTransaction'
22+// for wallet generation
23+import * as kg from '../../../node_modules/urbit-key-generation/dist/index'
24+import * as more from 'more-entropy'
25+import lodash from 'lodash'
26+import { PLANET_ENTROPY_BITS } from '../../walletgen/lib/constants'
28+// for transaction generation and signing
31+ sendSignedTransaction,
32+ waitForTransactionConfirm,
33+ isTransactionConfirmed
35+import * as tank from '../lib/tank'
36+import Tx from 'ethereumjs-tx'
38+//TODO needs more work to include email sending in the process
39+class InvitesSend extends React.Component {
45+ invitesAvailable: Nothing(),
47+ haveInvited: Nothing(),
48+ randomPlanet: Nothing(),
49+ inviteWallet: Nothing()
52+ this.findInvited = this.findInvited.bind(this);
53+ this.findRandomPlanet = this.findRandomPlanet.bind(this);
54+ this.generateWallet = this.generateWallet.bind(this);
55+ this.canGenerate = this.canGenerate.bind(this);
58+ componentDidMount() {
59+ this.point = this.props.pointCursor.matchWith({
60+ Just: (pt) => parseInt(pt.value, 10),
62+ throw BRIDGE_ERROR.MISSING_POINT
65+ this.contracts = this.props.contracts.matchWith({
66+ Just: cs => cs.value,
68+ throw BRIDGE_ERROR.MISSING_CONTRACTS
72+ azimuth.delegatedSending.getPool(this.contracts, this.point)
74+ this.setState({fromPool: Just(pool)});
75+ azimuth.delegatedSending.invitesInPool(this.contracts, pool)
77+ this.setState({invitesAvailable: Just(count)});
81+ this.findRandomPlanet();
82+ this.generateWallet();
85+ componentDidUpdate(prevProps) {
89+ async findInvited() {
90+ let invited = await azimuth.delegatedSending.getInvited(
94+ invited.map(async point => {
95+ const active = await azimuth.azimuth.isActive(this.contracts, point);
96+ console.log('point active', point, active);
97+ return {point: Number(point), active};
99+ invited = await Promise.all(invited);
100+ this.setState({haveInvited: Just(invited)});
103+ async findRandomPlanet() {
104+ let res = Nothing();
105+ const kids = azimuth.azimuth.getUnspawnedChildren(
107+ azimuth.azimuth.getPrefix(this.point)
109+ if (kids.length > 0) {
110+ const i = Math.floor(Math.random() * kids.length);
111+ res = Just(Number(kids[i]));
113+ this.setState({randomPlanet: res});
117+ //TODO pulled from walletgen/views/Generate, put into lib
118+ async generateWallet() {
119+ const makeTicket = () => {
121+ const bits = PLANET_ENTROPY_BITS
123+ const bytes = bits / 8
124+ const some = new Uint8Array(bytes)
125+ window.crypto.getRandomValues(some)
127+ const gen = new more.Generator()
129+ return new Promise((resolve, reject) => {
130+ gen.generate(bits, result => {
131+ const chunked = lodash.chunk(result, 2)
132+ const desired = chunked.slice(0, bytes) // only take required entropy
133+ const more = lodash.flatMap(desired, arr => arr[0] ^ arr[1])
134+ const entropy = lodash.zipWith(some, more, (x, y) => x ^ y)
135+ const buf = Buffer.from(entropy)
136+ const patq = ob.hex2patq(buf.toString('hex'))
138+ reject('Entropy generation failed')
143+ const ticket = await makeTicket(0x10000); // planet-sized ticket
144+ const wallet = await kg.generateWallet({ticket, ship:0});
145+ console.log('found ticket', ticket, wallet, wallet.ownership.keys.address);
146+ this.setState({inviteWallet:
147+ Just({ticket, owner:wallet.ownership.keys.address})
152+ //TODO and canSend()
153+ console.log('can generate', this.state.invitesAvailable, this.state.randomPlanet,);
154+ let res = this.state.invitesAvailable.matchWith({
155+ Nothing: () => false,
156+ Just: invites => ((invites.value > 0)
157+ && Just.hasInstance(this.state.randomPlanet)
158+ && Just.hasInstance(this.state.inviteWallet))
165+ const inviteStatus = this.state.invitesAvailable.matchWith({
166+ Nothing: () => 'Loading...',
167+ Just: (invites) => {
168+ let res = `${invites.value} invites available`;
169+ return res + this.state.fromPool.matchWith({
171+ Just: (pool) => (pool.value == this.point)
173+ : ` (from ${ob.patp(pool.value)})`
179+ const inviteList = this.state.haveInvited.matchWith({
180+ Nothing: () => (<li>{'Loading...'}</li>),
181+ Just: (invited) => invited.value.map(i => {
183+ <span class="invitee">{ob.patp(i.point)}</span>
184+ <span class="status">{i.active ? 'accepted' : 'pending'}</span>
193+ <p>{ 'send invites here, for planets' }</p>
195+ <p>{ inviteStatus }</p>
197+ <ul>{ inviteList }</ul>
199+ <StatelessTransaction
201+ web3={this.props.web3}
202+ contracts={this.props.contracts}
203+ wallet={this.props.wallet}
204+ walletType={this.props.walletType}
205+ walletHdPath={this.props.walletHdPath}
206+ networkType={this.props.networkType}
207+ setTxnHashCursor={this.props.setTxnHashCursor}
208+ setTxnConfirmations={this.props.setTxnConfirmations}
209+ popRoute={this.props.popRoute}
210+ pushRoute={this.props.pushRoute}
212+ canGenerate={this.canGenerate()}
213+ createUnsignedTxn={this.createUnsignedTxn}
214+ ref={this.statelessRef} />
222+export default InvitesSend