@@ -0,0 +1,122 @@
1+import React, { useState } from 'react';
2+import { Grid, Text } from 'indigo-react';
4+import { useLocalRouter } from 'lib/LocalRouter';
6+import View from 'components/View';
7+import Highlighted from 'components/Highlighted';
8+import CopiableAddressWrap from 'components/CopiableAddressWrap';
9+import ViewHeader from 'components/ViewHeader';
10+import SubmitButton from 'form/SubmitButton';
12+import { useWallet } from 'store/wallet';
14+import * as need from 'lib/need';
15+import * as bitcoin from 'bitcoinjs-lib';
17+import BridgeForm from 'form/BridgeForm';
18+import { PsbtInput } from 'form/Inputs';
20+import { Buffer } from 'buffer';
21+import { composeValidator, buildPsbtValidator } from 'form/validators';
23+export 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(
34+ const btcWallet = bitcoin.bip32.fromPrivateKey(
35+ Buffer.from(privKey, 'hex'),
36+ Buffer.from(chain, 'hex'),
37+ bitcoin.networks.bitcoin
40+ const validate = composeValidator({
41+ unsignedTransaction: buildPsbtValidator(btcWallet),
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'/")
52+ const prv = btcWallet.derivePath(path).privateKey;
54+ return psbt.signInput(idx, bitcoin.ECPair.fromPrivateKey(prv));
60+ .extractTransaction()
68+ <View pop={pop} inset>
69+ <Grid className="mt4">
70+ <Grid.Item full className="mt4" as={Text}>
71+ Paste unsigned transactions from Landscape here
73+ <BridgeForm validate={validate} onSubmit={onSubmit}>
74+ {({ handleSubmit }) => (
79+ name="unsignedTransaction"
80+ label="Unsigned transaction"
88+ handleSubmit={handleSubmit}
96+ <Grid.Item full className="mt4" as={Text}>
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>
109+ <Grid.Item full className="mt4" as={ViewHeader}>
112+ <Grid.Item full as={Text}>
114+ <CopiableAddressWrap>{signedTx}</CopiableAddressWrap>