-
Notifications
You must be signed in to change notification settings - Fork 12
/
check.js
803 lines (752 loc) · 24.1 KB
/
check.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
/**
* Contract checks, assertions, and verifications
* @module check
*/
const eclipticAbi = require('azimuth-solidity/build/contracts/Ecliptic.json').abi;
const ecliptic = require('./ecliptic');
const azimuth = require('./azimuth');
const linearSR = require('./linearSR')
const conditionalSR = require('./conditionalSR')
const polls = require('./polls');
const delegatedSending = require('./delegatedSending');
const utils = require('./utils');
const reasons = require('./resources/reasons.json');
const MAXGALAXY = 255;
const MAXSTAR = 65535;
const MAXPLANET = 4294967295;
/**
* Check if something is a point.
* @param {Number} point - Point number.
* @return {Bool} True if a point, false otherwise.
*/
function isPoint(point) {
return (typeof point === 'number' && point >= 0 && point <= MAXPLANET);
}
/**
* Check if something is a galaxy.
* @param {Number} point - Point number.
* @return {Bool} True if a galaxy, false otherwise.
*/
function isGalaxy(point) {
return (typeof point === 'number' && point >= 0 && point <= MAXGALAXY);
}
/**
* Check if something is a star.
* @param {Number} point - Point number.
* @return {Bool} True if a star, false otherwise.
*/
function isStar(point) {
return (typeof point === 'number' && point > MAXGALAXY && point <= MAXSTAR);
}
/**
* Check if something is a planet.
* @param {Number} point - Point number.
* @return {Bool} True if a planet, false otherwise.
*/
function isPlanet(point) {
return (typeof point === 'number' && point > MAXSTAR && point <= MAXPLANET);
}
/**
* Check if a point is a prefix of another point.
* @param {Number} point - Point number.
* @return {Bool} True if a prefix, false otherwise.
*/
function isPrefix(point) {
return (typeof point === 'number' && point >= 0 && point <= MAXSTAR);
}
/**
* Check if a point is a child of another point.
* @param {Number} point - Point number.
* @return {Bool} True if a child, false otherwise.
*/
function isChild(point) {
return (typeof point === 'number' && point > MAXGALAXY && point <= MAXPLANET);
}
/**
* Check if a poll is active.
* @param {Object} poll - A poll object.
* @return {Bool} True if active, false otherwise.
*/
function pollIsActive(poll) {
let now = Math.round(new Date().getTime()/1000);
let end = poll.start + poll.duration;
return now < end;
}
/**
* Check if a poll can be started.
* @param {Object} poll - A poll object.
* @return {Bool} True if so, false otherwise.
*/
function canStartPoll(poll) {
let now = Math.round(new Date().getTime()/1000);
let start = poll.start + poll.duration + poll.coolDown;
return now > start;
}
/**
* Check if a point has an owner.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} pointId - Point number.
* @return {Promise<Bool>} True if so, false otherwise.
*/
async function hasOwner(contracts, point) {
if (typeof point === 'object') {
return !utils.addressEquals(point.owner, utils.zeroAddress());
}
return !await azimuth.isOwner(contracts, point, utils.zeroAddress());
}
/**
* Check if an address is the ecliptic owner.
* @param {Object} contracts - An Urbit contracts object.
* @param {String} address - Owner's address.
* @return {Promise<Bool>} True if so, false otherwise.
*/
async function isEclipticOwner(contracts, address) {
return utils.addressEquals(address, await ecliptic.owner(contracts));
}
// NB (jtobin):
//
// Change the { result, reason } objects to use data.either or
// folktale.Result at some point.
/**
* Check if an address can create the specified galaxy.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} pointId - Point number.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canCreateGalaxy(contracts, galaxy, address) {
let res = { result: false };
// can't target zero address
if (utils.isZeroAddress(address)) {
res.reason = reasons.zero;
return res;
}
// must be ecliptic owner
if (!await isEclipticOwner(contracts, address)) {
res.reason = reasons.permission;
return res;
}
// can't already exist
if (await hasOwner(contracts, galaxy)) {
res.reason = reasons.spawned;
return res;
}
res.result = true;
return res;
}
/**
* Check if an address can spawn the given point.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} pointId - Point number.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canSpawn(contracts, point, target) {
let res = { result: false };
// prevents targeting the zero address
if (utils.isZeroAddress(target)) {
res.reason = reasons.zero;
return res;
}
let prefix = azimuth.getPrefix(point);
let prefixPointObj = await azimuth.getPoint(contracts, prefix);
// must either be the owner of the prefixPointObj, or a spawn proxy for it
if (!azimuth.isOwner(contracts, prefixPointObj, target) &&
!azimuth.isSpawnProxy(contracts, prefixPointObj, target))
{
res.reason = reasons.permission;
return res;
}
// only currently unowned points can be spawned
if (await hasOwner(contracts, point)) {
res.reason = reasons.spawned;
return res;
}
// only allow spawning of points of the size directly below the prefix
let childSize = azimuth.getPointSize(prefix) + 1;
let pointSize = azimuth.getPointSize(point);
if (childSize !== pointSize) {
res.reason = reasons.spawnSize;
return res;
}
// prefix must be linked and able to spawn
let ts = Math.round(new Date().getTime() / 1000);
let spawnLimit = await ecliptic.getSpawnLimit(contracts, prefix, ts);
if (!azimuth.hasBeenLinked(contracts, prefixPointObj) ||
(await azimuth.getSpawnCount(contracts, point)) >= spawnLimit)
{
res.reason = reasons.spawnPrefix;
return res;
}
res.result = true
return res;
}
async function canSetManagementProxy(contracts, point, address) {
return checkActivePointOwner(contracts, point, address);
}
async function canSetVotingProxy(contracts, point, address) {
if (!isGalaxy(point)) return { result: false, reason: reasons.notGalaxy };
return checkActivePointOwner(contracts, point, address);
}
/**
* Check if an address can set a spawn proxy for the given point.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} pointId - Point number.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canSetSpawnProxy(contracts, prefix, address) {
return checkActivePointOwner(contracts, prefix, address);
}
/**
* Check if the sender address can send the provided point to the target
* address.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} pointId - Point number.
* @param {String} sender - Sender's address.
* @param {String} target - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canTransferPoint(contracts, point, source, target) {
let res = { result: false };
// prevent burning of points
if (utils.isZeroAddress(target))
{
res.reason = reasons.zero;
return res;
}
let pointObj = await azimuth.getPoint(contracts, point);
// must be either the owner of the point,
// a transfer proxy for the point,
// or an operator for the owner
if (!azimuth.isOwner(contracts, pointObj, source) &&
!azimuth.isTransferProxy(contracts, pointObj, source) &&
!await azimuth.isOperator(contracts, pointObj.owner, source))
{
res.reason = reasons.permission;
return res;
}
res.result = true;
return res;
}
/**
* Check if the address can set a transfer proxy for the point.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} pointId - Point number.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canSetTransferProxy(contracts, point, address) {
let res = { result: false };
let pointObj = await azimuth.getPoint(contracts, point);
// must be either the owner of the point,
// or an operator for the owner
if (!azimuth.isOwner(contracts, pointObj, address) &&
!await azimuth.isOperator(contracts, pointObj.owner, address))
{
res.reason = reasons.permission;
return res;
}
res.result = true;
return res;
}
/**
* Check if the target address can make a point escape to the given sponsor.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} point - Point number.
* @param {Number} sponsor - Point number.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canEscape(contracts, point, sponsor, address) {
let asm = await checkActivePointManager(contracts, point, address);
if (!asm.result) {
return asm;
}
let res = { result: false };
let pointSize = azimuth.getPointSize(point);
let sponsorSize = azimuth.getPointSize(sponsor);
// can only escape to a point one size higher than ourselves,
// except in the special case where the escaping point hasn't
// been booted yet -- in that case we may escape to points of
// the same size, to support lightweight invitation chains.
if (sponsorSize + 1 !== pointSize &&
!(sponsorSize === pointSize &&
!await azimuth.hasBeenLinked(contracts, point)))
{
res.reason = reasons.sponsor;
return res;
}
// can't escape to a sponsor that hasn't been booted
if (!await azimuth.hasBeenLinked(contracts, sponsor))
{
res.reason = reasons.sponsorBoot;
return res;
}
res.result = true;
return res;
}
/**
* Check if a point is active and the target address is its owner.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} point - Point number.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function checkActivePointOwner(contracts, point, address) {
let res = { result: false };
let thePoint = await azimuth.getPoint(contracts, point);
// must be the owner of the point
if (!await azimuth.isOwner(contracts, thePoint, address)) {
res.reason = reasons.permission;
return res;
}
// the point must be active
if (!await azimuth.isActive(contracts, thePoint)) {
res.reason = reasons.inactive;
return res;
}
res.result = true;
return res;
}
/**
* Check if a point is active and the target address can manage it.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} point - Point number.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function checkActivePointManager(contracts, point, address) {
let res = { result: false };
if (!await azimuth.canManage(contracts, point, address))
{
res.reason = reasons.permission;
return res;
}
if (!await azimuth.isActive(contracts, point))
{
res.reason = reasons.inactive;
return res;
}
res.result = true;
return res;
}
/**
* Check if an address can configure public keys for a point.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} point - Point number.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canConfigureKeys(contracts, point, address) {
return await checkActivePointManager(contracts, point, address);
}
/**
* Check if the target address can adopt the escapee as its new sponsor.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} escapee - Escapee's point number.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canAdopt(contracts, escapee, address) {
let res = { result: false };
// escapee must currently be trying to escape
let point = await azimuth.getPoint(contracts, escapee, 'state');
if (!point.escapeRequested) {
res.reason = reasons.notEscape;
return res;
}
// caller must manage the requested sponsor
return await checkActivePointManager(contracts, point.escapeRequestedTo, address);
}
/**
* Check if the target address can reject the escapee's request to the given
* sponsor.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} escapee - Escapee's point number.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canReject(contracts, escapee, address) {
// check is currently identical to adopt()'s.
return await canAdopt(contracts, escapee, address);
}
/**
* Check if the target address can detach a point from its sponsor.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} point - Point number.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canDetach(contracts, point, address)
{
let res = { result: false };
// point must currently have a sponsor
let thePoint = await azimuth.getPoint(contracts, point, 'state');
if (!thePoint.hasSponsor) {
res.reason = reasons.sponsorless;
return res;
}
// caller must manage the requested sponsor
return await checkActivePointManager(contracts, thePoint.sponsor, address);
}
/**
* Check if a point is active and an address can vote for it.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} point - Point number.
* @param {String} voter - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function checkActivePointVoter(contracts, galaxy, voter) {
let res = { result: false }
if (azimuth.getPointSize(galaxy) !== azimuth.PointSize.Galaxy)
{
res.reason = reasons.notGalaxy;
return res;
}
if (!await azimuth.canVoteAs(contracts, galaxy, voter))
{
res.reason = reasons.permission;
return res;
}
if (!await azimuth.isActive(contracts, galaxy))
{
res.reason = reasons.inactive;
return res;
}
res.result = true;
return res;
}
/**
* Check if a target address and point can initiate a upgrade poll at the
* given address.
* @param {Object} web3 - A web3 object.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} galaxy - A (galaxy) point number.
* @param {String} proposal - The proposal address.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canStartUpgradePoll(web3, contracts, galaxy, proposal, address) {
let asv = await checkActivePointVoter(contracts, galaxy, address);
if (!asv.result) return asv;
let res = { result: false};
let prop = new web3.eth.Contract(eclipticAbi, proposal);
let expected;
try {
expected = await prop.methods.previousEcliptic().call()
} catch(e) {
expected = null;
}
if (!expected || !utils.addressEquals(contracts.ecliptic.address, expected))
{
res.reason = reasons.upgradePath;
return res;
}
if (await polls.eclipticHasAchievedMajority(contracts, proposal))
{
res.reason = reasons.majority;
return res;
}
if (!canStartPoll(await polls.getUpgradePoll(contracts, proposal)))
{
res.reason = reasons.pollTime;
return res;
}
res.result = true;
return res;
}
/**
* Check if a target address and point can initiate the given proposal.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} galaxy - A (galaxy) point number.
* @param {String} proposal - The proposal address.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canStartDocumentPoll(contracts, galaxy, proposal, address) {
let asv = await checkActivePointVoter(contracts, galaxy, address);
if (!asv.result) return asv;
let res = { result: false };
if (await polls.documentHasAchievedMajority(contracts, proposal))
{
res.reason = reasons.majority;
return res;
}
if (!canStartPoll(await polls.getDocumentPoll(contracts, proposal)))
{
res.reason = reasons.pollTime;
return res;
}
res.result = true;
return res;
}
/**
* Check if a target address and point can vote on the proposal at the target
* address.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} galaxy - A (galaxy) point number.
* @param {String} proposal - The proposal address.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canCastUpgradeVote(contracts, galaxy, proposal, address)
{
let asv = await checkActivePointVoter(contracts, galaxy, address);
if (!asv.result) return asv;
let res = { result: false };
// proposal must not have achieved majority before
if (await polls.eclipticHasAchievedMajority(contracts, proposal))
{
res.reason = reasons.majority;
return res;
}
// may only vote when the poll is open
if (!pollIsActive(await polls.getUpgradePoll(contracts, proposal)))
{
res.reason = reasons.pollInactive;
return res;
}
// may only vote once
if (await polls.hasVotedOnUpgradePoll(contracts, galaxy, proposal))
{
res.reason = reasons.pollVoted;
return res;
}
res.result = true;
return res;
}
/**
* Check if a target address and point can vote on the proposal at the given
* address.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} galaxy - A (galaxy) point number.
* @param {String} proposal - The proposal address.
* @param {String} address - Target address.
* @return {Promise<Object>} A result and reason pair.
*/
async function canCastDocumentVote(contracts, galaxy, proposal, address)
{
let asv = await checkActivePointVoter(contracts, galaxy, address);
if (!asv.result) return asv;
let res = { result: false };
// proposal must not have achieved majority before
if (await polls.documentHasAchievedMajority(contracts, proposal))
{
res.reason = reasons.majority;
return res;
}
// may only vote when the poll is open
if (!pollIsActive(await polls.getDocumentPoll(contracts, proposal)))
{
res.reason = reasons.pollInactive;
return res;
}
// may only vote once
if (await polls.hasVotedOnDocumentPoll(contracts, galaxy, proposal))
{
res.reason = reasons.pollVoted;
return res;
}
res.result = true;
return res;
}
/**
* Check if the target address can set the DNS domains for the ecliptic.
* @param {Object} contracts - An Urbit contracts object.
* @param {String} address - Target address.
* @return {Promise<Bool>} True if so, false otherwise.
*/
function canSetDnsDomains(contracts, address) {
return isEclipticOwner(contracts, address);
}
/**
* Check if the address can withdraw a star from their batch at this moment.
* @param {Object} contracts - An Urbit contracts object.
* @param {String} address - The participant/registered address for the batch.
* @return {Promise<Object>} A result and reason pair.
*/
async function lsrCanWithdraw(contracts, address) {
let res = { result: false };
let rem = await linearSR.getRemainingStars(contracts, address);
if (rem.length === 0) {
res.reason = reasons.noRemaining;
return res;
}
let bas = await linearSR.getBatch(contracts, address);
let lim = await linearSR.getWithdrawLimit(contracts, address);
if (bas.withdrawn >= lim) {
res.reason = reasons.withdrawLimit;
return res;
}
res.result = true;
return res;
}
/**
* Check if the address can withdraw a star from their batch at this moment.
* @param {Object} contracts - An Urbit contracts object.
* @param {String} from - The participant/registered address for the batch.
* @param {String} to - The intended new address of the participant.
* @return {Promise<Object>} A result and reason pair.
*/
async function lsrCanTransferBatch(contracts, from, to) {
let res = { result: false };
let apr = await linearSR.getApprovedTransfer(contracts, from);
if (to !== apr) {
res.reason = reasons.notApproved;
return res;
}
res.result = true;
return res;
}
/**
* Check if the address can withdraw a star from their commitment at this moment.
* @param {Object} contracts - An Urbit contracts object.
* @param {String} address - The participant/registered address for the commitment.
* @return {Promise<Object>} A result and reason pair.
*/
async function csrCanWithdraw(contracts, address) {
let res = { result: false };
let rem = await conditionalSR.getRemainingStars(contracts, address);
if (rem.length === 0) {
res.reason = reasons.noRemaining;
return res;
}
let com = await conditionalSR.getCommitment(contracts, address);
let lim = await conditionalSR.getWithdrawLimit(contracts, address);
// cannot withdraw more than the limit
if (com.withdrawn >= lim) {
res.reason = reasons.withdrawLimit;
return res;
}
// cannot withdraw forfeited stars
if (com.forfeit && rem.length <= com.forfeited) {
res.reason = reasons.forfeitLimit;
return res;
}
res.result = true;
return res;
}
/**
* Check if the address can withdraw a star from their commitment at this moment.
* @param {Object} contracts - An Urbit contracts object.
* @param {String} from - The participant/registered address for the commitment.
* @param {String} to - The intended new address of the participant.
* @return {Promise<Object>} A result and reason pair.
*/
async function csrCanTransferBatch(contracts, from, to) {
let res = { result: false };
let apr = await conditionalSR.getApprovedTransfer(contracts, from);
if (to !== apr) {
res.reason = reasons.notApproved;
return res;
}
res.result = true;
return res;
}
/**
* Check if the address can forfeit their commitment starting at the batch.
* @param {Object} contracts - An Urbit contracts object.
* @param {Number} batch - The batch they want to forfeit from.
* @param {String} address - The participant/registered address for the
* commitment.
* @return {Promise<Object>} A result and reason pair.
*/
async function csrCanForfeit(contracts, batch, address) {
let res = { result: false };
let com = await conditionalSR.getCommitment(contracts, address);
// can only forfeit if not yet forfeited,
if (com.forfeit) {
res.reason = reasons.hasForfeited;
return res;
}
let det = await conditionalSR.getConditionsState(contracts);
// and deadline has been missed.
if (det.deadlines[batch] !== det.timestamps[batch]) {
res.reason = reasons.notMissed;
return res;
}
res.result = true;
return res;
}
/**
* Check if the address can give invites to point
* @param {Number} point - Point number to give invites to
* @param {String} address - The caller address
* @return {Promise<Object>} A result and reason pair
*/
async function canSetPoolSize(contracts, point, address) {
return checkActivePointOwner(contracts, azimuth.getPrefix(point), address);
}
/**
* Check if as can send point as an invite to to
* @param {Number} as - The point that would send the invite
* @param {Number} point - The point that would be sent as invite
* @param {String} to - The Ethereum address recipient of the invite
* @param {String} address - The caller address
* @return {Promise<Object>} A result and reason pair
*/
async function canSendInvitePoint(contracts, as, point, to, address) {
let res = await checkActivePointOwner(contracts, as, address);
if (!res.result) {
return res;
}
res.result = false;
if (utils.addressEquals(to, address)) {
res.reason = reasons.cantReceive;
return res;
}
let canSend = await delegatedSending.canSend(contracts, as, point);
if (!canSend) {
res.reason = reasons.permission;
return res;
}
let canReceive = await delegatedSending.canReceive(contracts, to);
if (!canReceive) {
res.reason = reasons.cantReceive;
return res;
}
res.result = true;
return res;
}
module.exports = {
ecliptic,
azimuth,
polls,
isPoint,
isGalaxy,
isStar,
isPlanet,
isPrefix,
isChild,
pollIsActive,
canStartPoll,
hasOwner,
isEclipticOwner,
canCreateGalaxy,
canSpawn,
canSetManagementProxy,
canSetVotingProxy,
canSetSpawnProxy,
canTransferPoint,
canSetTransferProxy,
canConfigureKeys,
canEscape,
canAdopt,
canReject,
canDetach,
checkActivePointManager,
checkActivePointVoter,
canStartUpgradePoll,
canStartDocumentPoll,
canCastUpgradeVote,
canCastDocumentVote,
canSetDnsDomains,
lsrCanWithdraw,
lsrCanTransferBatch,
csrCanWithdraw,
csrCanTransferBatch,
csrCanForfeit,
canSetPoolSize,
canSendInvitePoint,
}