@@ -1,155 +0,0 @@
1−import React, { useState } from 'react';
2−import { Grid, Text } from 'indigo-react';
3−import { useWallet } from 'store/wallet';
4−
5−import { useLocalRouter } from 'lib/LocalRouter';
6−
7−import ViewHeader from 'components/ViewHeader';
8−import View from 'components/View';
9−import WarningBox from 'components/WarningBox';
10−
11−import CopiableAddressWrap from 'components/CopiableAddressWrap';
12−import Highlighted from 'components/Highlighted';
13−
14−import { PsbtInput } from 'form/Inputs';
15−import BridgeForm from 'form/BridgeForm';
16−
17−import * as need from 'lib/need';
18−import * as bitcoin from 'bitcoinjs-lib';
19−import * as bs58check from 'bs58check';
20−import { Buffer } from 'buffer';
21−import { composeValidator, buildPsbtValidator } from 'form/validators';
22−
23−function xpubToZpub(xpub) {
24− var data = bs58check.decode(xpub);
25− data = data.slice(4);
26− data = Buffer.concat([Buffer.from('04b24746', 'hex'), data]);
27− return bs58check.encode(data);
28−}
29−
30−export default function Bitcoin() {
31− const { pop } = useLocalRouter();
32− const { urbitWallet } = useWallet();
33−
34−
35− const empty = new bitcoin.Psbt();
36−
37− const [signedTx, setSignedTx] = useState('');
38− const [psbt, setPsbt] = useState(empty);
39−
40− const privKey = need.urbitWallet(urbitWallet).bitcoin.keys.private;
41− const pubKey = need.urbitWallet(urbitWallet).bitcoin.keys.public;
42− const chain = need.urbitWallet(urbitWallet).bitcoin.keys.chain;
43−
44− const btcWallet = bitcoin.bip32.fromPrivateKey(
45− Buffer.from(privKey, 'hex'),
46− Buffer.from(chain, 'hex'),
47− bitcoin.networks.bitcoin
48− );
49−
50− const zPub = xpubToZpub(
51− bitcoin.bip32
52− .fromPublicKey(
53− Buffer.from(pubKey, 'hex'),
54− Buffer.from(chain, 'hex'),
55− bitcoin.networks.bitcoin
56− )
57− .toBase58()
58− );
59−
60− const validate = composeValidator({
61− unsignedTransaction: buildPsbtValidator(btcWallet),
62− });
63−
64− const onValues = ({ valid, values, form }) => {
65− if (valid) {
66− const newPsbt = bitcoin.Psbt.fromBase64(values.unsignedTransaction);
67− const hex = newPsbt.data.inputs
68− .reduce((psbt, input, idx) => {
69− // removing already derived part, eg m/84'/0'/0'/0/0 becomes 0/0
70− const path = input.bip32Derivation[0].path
71− .split("m/84'/0'/0'/")
72− .join('');
73− const prv = btcWallet.derivePath(path).privateKey;
74− try {
75− return psbt.signInput(idx, bitcoin.ECPair.fromPrivateKey(prv));
76− } catch (e) {
77− return psbt;
78− }
79− }, newPsbt)
80− .finalizeAllInputs()
81− .extractTransaction()
82− .toHex();
83−
84− if (psbt.toHex() !== newPsbt.toHex()) {
85− setPsbt(newPsbt);
86− }
87− setSignedTx(hex);
88− } else {
89− setSignedTx('');
90− }
91− };
92−
93− return (
94− <View pop={pop} inset>
95− <Grid className="mt4">
96− <Grid.Item full as={ViewHeader}>
97− Bitcoin
98− </Grid.Item>
99− <Grid.Item full as={WarningBox}>
100− We do not recommend using this feature for significant amounts of
101− money, since your private keys are exposed to the browser.
102− </Grid.Item>
103− <Grid.Item full className="mt4" as={Text}>
104− Below is the bitcoin extended public key derived from your master
105− ticket. You can paste it to Landscape to generate an unsigned
106− transaction.
107− </Grid.Item>
108− <Grid.Item full className="mt4" as={Text}>
109− <Highlighted>
110− <CopiableAddressWrap>{zPub}</CopiableAddressWrap>
111− </Highlighted>
112− </Grid.Item>
113− <Grid.Item full className="mt4" as={Text}>
114− Next, paste the unsigned transaction below to sign it with your
115− private key.
116− </Grid.Item>
117− <BridgeForm validate={validate} onValues={onValues}>
118− {() => (
119− <Grid.Item
120− full
121− as={PsbtInput}
122− name="unsignedTransaction"
123− label="Unsigned transaction"
124− className="mt4"
125− />
126− )}
127− </BridgeForm>
128− {signedTx && (
129− <Grid.Item full className="mt4" as={Text}>
130− Transaction outputs:
131− </Grid.Item>
132− )}
133− {signedTx &&
134− psbt.txOutputs.map(e => (
135− <Grid.Item full className="mt4" key={e.address}>
136− <span>{e.address}</span>
137− <div className="mt1 mono black f6">{e.value} Satoshis</div>
138− </Grid.Item>
139− ))}
140− {signedTx && (
141− <>
142− <Grid.Item full className="mt4" as={ViewHeader}>
143− Signed transaction:
144− </Grid.Item>
145− <Grid.Item full as={Text}>
146− <Highlighted>
147− <CopiableAddressWrap>{signedTx}</CopiableAddressWrap>
148− </Highlighted>
149− </Grid.Item>
150− </>
151− )}
152− </Grid>
153− </View>
154− );
155−}