on f3b6250 help sign in
bridge/src/views/Bitcoin/SignTransaction.js
122 lines 3.6 kB history raw
1import React, { useState } from 'react';
2import { Grid, Text } from 'indigo-react';
4import { useLocalRouter } from 'lib/LocalRouter';
6import View from 'components/View';
7import Highlighted from 'components/Highlighted';
8import CopiableAddressWrap from 'components/CopiableAddressWrap';
9import ViewHeader from 'components/ViewHeader';
10import SubmitButton from 'form/SubmitButton';
12import { useWallet } from 'store/wallet';
14import * as need from 'lib/need';
15import * as bitcoin from 'bitcoinjs-lib';
17import BridgeForm from 'form/BridgeForm';
18import { PsbtInput } from 'form/Inputs';
20import { Buffer } from 'buffer';
21import { composeValidator, buildPsbtValidator } from 'form/validators';
23export default function SignTransaction() {
24 const { pop } = useLocalRouter();
25 const { urbitWallet } = useWallet();
27 const [signedTx, setSignedTx] = useState('');
28 const [psbt, setPsbt] = useState({});
30 const { private: privKey, chain } = need.urbitWallet(
31 urbitWallet
32 ).bitcoin.keys;
34 const btcWallet = bitcoin.bip32.fromPrivateKey(
35 Buffer.from(privKey, 'hex'),
36 Buffer.from(chain, 'hex'),
37 bitcoin.networks.bitcoin
38 );
40 const validate = composeValidator({
41 unsignedTransaction: buildPsbtValidator(btcWallet),
42 });
44 const onSubmit = values => {
45 const newPsbt = bitcoin.Psbt.fromBase64(values.unsignedTransaction);
46 const hex = newPsbt.data.inputs
47 .reduce((psbt, input, idx) => {
48 // removing already derived part, eg m/84'/0'/0'/0/0 becomes 0/0
49 const path = input.bip32Derivation[0].path
50 .split("m/84'/0'/0'/")
51 .join('');
52 const prv = btcWallet.derivePath(path).privateKey;
53 try {
54 return psbt.signInput(idx, bitcoin.ECPair.fromPrivateKey(prv));
55 } catch (e) {
56 return psbt;
57 }
58 }, newPsbt)
59 .finalizeAllInputs()
60 .extractTransaction()
61 .toHex();
63 setPsbt(newPsbt);
64 setSignedTx(hex);
65 };
67 return (
68 <View pop={pop} inset>
69 <Grid className="mt4">
70 <Grid.Item full className="mt4" as={Text}>
71 Paste unsigned transactions from Landscape here
72 </Grid.Item>
73 <BridgeForm validate={validate} onSubmit={onSubmit}>
74 {({ handleSubmit }) => (
75 <>
76 <Grid.Item
77 full
78 as={PsbtInput}
79 name="unsignedTransaction"
80 label="Unsigned transaction"
81 className="mt4"
82 />
83 <Grid.Item
84 full
85 solid
86 className="mt2"
87 accessory=""
88 handleSubmit={handleSubmit}
89 as={SubmitButton}>
90 Sign Transaction
91 </Grid.Item>
92 </>
93 )}
94 </BridgeForm>
95 {signedTx && (
96 <Grid.Item full className="mt4" as={Text}>
97 Transaction outputs:
98 </Grid.Item>
99 )}
100 {signedTx &&
101 psbt.txOutputs.map(e => (
102 <Grid.Item full className="mt4" key={e.address}>
103 <span>{e.address}</span>
104 <div className="mt1 mono black f6">{e.value} sats</div>
105 </Grid.Item>
106 ))}
107 {signedTx && (
108 <>
109 <Grid.Item full className="mt4" as={ViewHeader}>
110 Signed transaction:
111 </Grid.Item>
112 <Grid.Item full as={Text}>
113 <Highlighted>
114 <CopiableAddressWrap>{signedTx}</CopiableAddressWrap>
115 </Highlighted>
116 </Grid.Item>
117 </>
118 )}
119 </Grid>
120 </View>
121 );