on df0c310 help sign in
bridge/src/views/Release/TransferForm.tsx
156 lines 4.9 kB history raw
1import * as need from 'lib/need';
2import CopiableAddress from 'components/copiable/CopiableAddress';
3import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
4import NoticeBox from 'components/NoticeBox';
5import BridgeForm from 'form/BridgeForm';
6import FormError from 'form/FormError';
7import { AddressInput } from 'form/Inputs';
8import { composeValidator } from 'form/validators';
9import { Grid, Flex } from 'indigo-react';
10import { useCallback, useEffect, useMemo } from 'react';
11import { useHistory } from 'store/history';
12import { useNetwork } from 'store/network';
13import { useStarReleaseCache } from 'store/starRelease';
14import { useWallet } from 'store/wallet';
15import { eqAddr, isZeroAddress } from 'lib/utils/address';
16import { useTransferLockup } from './useTransferLockup';
17import { isValidAddress } from '@ethereumjs/util';
18import { getLockupKind } from 'lib/starRelease';
20interface TransferFormProps {
21 afterSubmit: VoidFunction;
24export const TransferForm = ({ afterSubmit }: TransferFormProps) => {
25 const { wallet }: any = useWallet();
26 const { contracts }: any = useNetwork();
27 const { pop }: any = useHistory();
28 const address = need.addressFromWallet(wallet);
30 const {
31 syncStarReleaseDetails,
32 starReleaseDetails,
33 }: any = useStarReleaseCache();
35 useEffect(() => {
36 syncStarReleaseDetails();
37 }, [syncStarReleaseDetails]);
39 const kind = useMemo(() => {
40 return starReleaseDetails.map((a: any) => a.kind).getOrElse('') ===
41 'conditional'
42 ? 'conditional'
43 : 'linear';
44 }, [starReleaseDetails]);
46 const approvedFor = useMemo(() => {
47 let approved;
48 if (kind === 'conditional') {
49 approved = starReleaseDetails.map(
50 (a: any) => a.conditional.approvedTransferTo
51 );
52 } else {
53 approved = starReleaseDetails.map(
54 (a: any) => a.linear.approvedTransferTo
55 );
56 }
57 approved = approved.getOrElse('0x0');
58 if (isZeroAddress(approved) || eqAddr(approved, address)) {
59 return false;
60 } else {
61 return approved;
62 }
63 }, [starReleaseDetails, kind, address]);
65 const {
66 bind,
67 construct,
68 unconstruct,
69 inputsLocked,
70 completed,
71 } = useTransferLockup(kind);
73 const onValues = useCallback(
74 async ({ valid, values }) => {
75 if (valid) {
76 construct(values.to);
77 } else {
78 unconstruct();
79 }
80 },
81 [construct, unconstruct]
82 );
84 const validate = useMemo(
85 () =>
86 composeValidator({
87 to: async (to: string) => {
88 if (!isValidAddress(to)) {
89 return 'This is not a valid Ethereum address.';
90 }
91 const theirs = await getLockupKind(need.contracts(contracts), to);
92 if (theirs === kind || theirs === 'both') {
93 return `Target address already owns a ${kind} lockup.`;
94 }
95 },
96 }),
97 [kind, contracts]
98 );
100 return (
101 <>
102 <BridgeForm onValues={onValues} validate={validate}>
103 {({ values }: any) => (
104 <>
105 {!completed && (
106 <>
107 <Grid.Item full className="f5">
108 Allow the specified address to take over your {kind} lockup.
109 <br />
110 After they accept the transfer, you will no longer be able to{' '}
111 withdraw from this lockup.
112 </Grid.Item>
113 {approvedFor && (
114 <Grid.Item full as={NoticeBox}>
115 Transfer currently approved for{' '}
116 <CopiableAddress>{approvedFor}</CopiableAddress>
117 </Grid.Item>
118 )}
119 <Grid.Item full className="f5" cols={[1, 13]} as={Flex} col>
120 <Flex.Item
121 name="to"
122 as={AddressInput}
123 label="Approve transfer to"
124 disabled={inputsLocked}
125 />
126 </Grid.Item>
127 </>
128 )}
130 <Grid.Item full as={FormError} />
131 {completed && (
132 <>
133 <Grid.Item full className="pv4">
134 <CopiableAddress>{values.to}</CopiableAddress> is now allowed{' '}
135 to take ownership of this lockup. They can do so by visiting:
136 </Grid.Item>
137 <Grid.Item full as="code" className="f5 mb4 mono wrap">
138 https://bridge.urbit.org/?kind=takeLockup&lock={kind}
139 &from={address}
140 </Grid.Item>
141 <Grid.Divider />
142 </>
143 )}
144 <Grid.Item
145 full
146 as={InlineEthereumTransaction}
147 {...bind}
148 label="Approve Transfer"
149 onReturn={() => pop()}
150 />
151 </>
152 )}
153 </BridgeForm>
154 </>
155 );
156};