on master help sign in
InvitesSend touchups: comments, renames, funding message...
commit25f06c8ce7415991a94eb3d0ad5ecd826537c88e authorFang <git@fang.io> dateThu 6 Jun 2019, 20:42 (7 years ago) parent877bc6c
1 file changed+44−25
src/bridge/views/InvitesSend.js+44−25
src/bridge/views/InvitesSend.js+44−25
@@ -15,13 +15,15 @@ import {
1515 signTransaction,
1616 sendSignedTransaction,
1717 waitForTransactionConfirm,
18− hexify
18+ hexify,
19+ fromWei,
20+ toWei
1921} from '../lib/txn'
2022import * as tank from '../lib/tank'
2123
2224const GAS_PRICE_GWEI = 20; // we pay the premium for faster ux
23−const GAS_LIMIT = 500000; //TODO fine-tune
24−const INVITE_COST = (GAS_PRICE_GWEI * 1000000000 * GAS_LIMIT);
25+const GAS_LIMIT = 350000;
26+const INVITE_COST = toWei((GAS_PRICE_GWEI * GAS_LIMIT).toString(), 'gwei');
2527
2628const STATUS = {
2729 INPUT: 'Generate invites',
@@ -50,13 +52,15 @@ class InvitesSend extends React.Component {
5052 status: STATUS.INPUT,
5153 errors: Nothing(),
5254 //
53− invites: []
55+ fundingMessage: Nothing(),
56+ wipInvites: []
5457 }
5558
5659 this.findInvited = this.findInvited.bind(this);
5760 this.generateInvites = this.generateInvites.bind(this);
5861 this.sendInvites = this.sendInvites.bind(this);
5962 this.canSend = this.canSend.bind(this);
63+ this.addError = this.addError.bind(this);
6064 this.handleEmailInput = this.handleEmailInput.bind(this);
6165 this.addTarget = this.addTarget.bind(this);
6266 this.removeTarget = this.removeTarget.bind(this);
@@ -130,26 +134,27 @@ class InvitesSend extends React.Component {
130134
131135 const web3 = this.web3;
132136 const targets = this.state.targets;
133− console.log('getting planets');
134137 const planets = await azimuth.delegatedSending.getPlanetsToSend(
135138 this.contracts, this.point, targets.length
136139 );
137− console.log('got planets', planets.length);
140+
141+ // account for the race condition where invites got used up while we were
142+ // composing our target list
138143 if (planets.length < targets.length) {
139− //TODO proper display state
140− throw new Error('can currently only send '+planets.length+' invites...');
144+ this.addError('Can currently only send '+planets.length+' invites!');
145+ return;
141146 }
142147
143− let invites = []; // { recipient, ticket, signedTx, rawTx }
144− console.log('generating emails...');
145148 const nonce = await web3.eth.getTransactionCount(this.address);
146149 const chainId = await web3.eth.net.getId();
147− console.log('chainId', chainId);
150+
151+ // create invite wallets and transactions
152+ let invites = []; // { email, ticket, signedTx, rawTx }
148153 for (let i = 0; i < targets.length; i++) {
149154 console.log('generating email', i, targets[i].email);
150155 this.setEmailStatus(i, EMAIL_STATUS.BUSY);
151156
152− const recipient = targets[i].email;
157+ const email = targets[i].email;
153158 const wallet = await this.getTemporaryWallet();
154159
155160 let inviteTx = azimuth.delegatedSending.sendPoint(
@@ -166,15 +171,15 @@ class InvitesSend extends React.Component {
166171 });
167172 const rawTx = hexify(signedTx.serialize());
168173
169− invites.push({recipient, ticket: wallet.ticket, signedTx, rawTx });
174+ invites.push({email, ticket: wallet.ticket, signedTx, rawTx });
170175 this.setEmailStatus(i, EMAIL_STATUS.DONE);
171176 }
172177
173− this.setState({ invites, status: STATUS.CAN_SEND });
178+ this.setState({ wipInvites: invites, status: STATUS.CAN_SEND });
174179 }
175180
176181 async sendInvites() {
177− const invites = this.state.invites;
182+ const invites = this.state.wipInvites;
178183 const web3 = this.web3;
179184
180185 //TODO invite status isn't changing... why?
@@ -188,7 +193,7 @@ class InvitesSend extends React.Component {
188193 (INVITE_COST * invites.length),
189194 invites.map(i => i.rawTx), this.askForFunding
190195 );
191− this.setState({ message: Nothing() }); //TODO see /lib/tank waitForBalance
196+ this.setState({ fundingMessage: Nothing() }); //TODO see /lib/tank waitForBalance
192197
193198 this.setState({ status: STATUS.SENDING });
194199
@@ -200,14 +205,14 @@ class InvitesSend extends React.Component {
200205 web3, Just(invite.signedTx), tankWasUsed, ()=>{}
201206 ).catch(err => {
202207 console.error('invite tx sending failed', err);
203− this.addError('Invite transaction not sent for ' + invite.recipient);
208+ this.addError('Invite transaction not sent for ' + invite.email);
204209 this.setEmailStatus(i, EMAIL_STATUS.FAIL);
205210 });
206211
207212 // ask the email sender to send this. we can do this prior to tx confirm,
208213 // because the sender service waits for confirm & success for us.
209214 const mailSuccess = await sendMail(
210− invite.recipient, invite.ticket, invite.rawTx
215+ invite.email, invite.ticket, invite.rawTx
211216 );
212217 //TODO but this doesn't catch sender-side failures... we may
213218 // just need really good monitoring for that...
@@ -218,7 +223,7 @@ class InvitesSend extends React.Component {
218223 //NOTE this assumes that the transaction succeeds, but we don't know
219224 // that for a fact yet...
220225 this.addError(
221− 'Invite email failed to send for ' + invite.recipient +
226+ 'Invite email failed to send for ' + invite.email +
222227 '. Please give them this ticket: ' + invite.ticket
223228 );
224229 this.setEmailStatus(i, EMAIL_STATUS.FAIL);
@@ -229,7 +234,7 @@ class InvitesSend extends React.Component {
229234 .then(async success => {
230235 if (!success) {
231236 console.log('invite tx rejected');
232− this.addError('Invite transaction failed for ' + invite.recipient);
237+ this.addError('Invite transaction failed for ' + invite.email);
233238 this.setEmailStatus(i, EMAIL_STATUS.FAIL);
234239 }
235240 });
@@ -248,15 +253,16 @@ class InvitesSend extends React.Component {
248253 addError(error) {
249254 const newError = this.state.errors.matchWith({
250255 Nothing: () => [error],
251− Just: errs => errs.value.push(error)
256+ Just: errs => { errs.value.push(error); return errs.value; }
252257 });
253258 this.setState({ errors: Just(newError) });
254259 }
255260
256261 askForFunding(address, minBalance, balance) {
257− this.setState({ message: Just(
258− `Please make sure ${address} has at least ${minBalance} wei,` +
259− `we'll continue once that's true. Current balance: ${balance}. Waiting...`
262+ this.setState({ fundingMessage: Just(
263+ `Please make sure ${address} has at least ${fromWei(minBalance)} ETH,` +
264+ `we'll continue once that's true. Current balance: ${fromWei(balance)}.` +
265+ `Waiting...`
260266 ) });
261267 }
262268
@@ -264,6 +270,7 @@ class InvitesSend extends React.Component {
264270 let targets = this.state.targets;
265271 targets[i].email = email;
266272
273+ // if it's a valid address, check if it has received an invite before
267274 if (email.match(/.*@.*\...+/)) {
268275 hasReceived(email)
269276 .then(res => {
@@ -273,14 +280,18 @@ class InvitesSend extends React.Component {
273280 } else {
274281 targets[i].hasReceived = Nothing();
275282 }
283+
276284 this.setState({ targets });
277285 }
278286
279287 canSend() {
280288 const targets = this.state.targets;
289+
281290 // may not have duplicate targets
282291 if ((new Set(targets.map(t => t.email))).size !== targets.length)
283292 return false;
293+
294+ // none may have received invites already
284295 for (let i = 0; i < targets.length; i++) {
285296 const target = targets[i];
286297 const res = target.hasReceived.matchWith({
@@ -289,6 +300,7 @@ class InvitesSend extends React.Component {
289300 });
290301 if (res) return false;
291302 }
303+
292304 return this.state.invitesAvailable.matchWith({
293305 Nothing: () => false,
294306 Just: invites => (invites.value > 0)
@@ -328,7 +340,7 @@ class InvitesSend extends React.Component {
328340 }
329341 });
330342
331− let error = this.state.errors.matchWith({
343+ const error = this.state.errors.matchWith({
332344 Nothing: () => null,
333345 Just: (errors) => (<Warning className={'mt-8'}>
334346 <H3 style={{marginTop: 0, paddingTop: 0}}>
@@ -338,6 +350,11 @@ class InvitesSend extends React.Component {
338350 </Warning>)
339351 });
340352
353+ const fundingMessage = this.state.fundingMessage.matchWith({
354+ Nothing: () => null,
355+ Just: msg => (<Warning className={'mt-8'}>{msg.value}</Warning>)
356+ });
357+
341358 //TODO don't render inputs at all if STATUS.DONE
342359
343360 const inputDisabled = (this.state.status !== STATUS.INPUT);
@@ -378,6 +395,8 @@ class InvitesSend extends React.Component {
378395
379396 { error }
380397
398+ { fundingMessage }
399+
381400 <Button
382401 prop-size={'s narrow'}
383402 className={'mt-8'}