Skip to content

Commit 52daa40

Browse files
committed
Fix SP
1 parent 0c600ee commit 52daa40

File tree

1 file changed

+114
-42
lines changed

1 file changed

+114
-42
lines changed

src/navigation/SP.tsx

Lines changed: 114 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,148 @@
11
import * as bitcoin from "bitcoinjs-lib";
2-
import { UTXOType, UTXO} from "silent-payments";
2+
import { UTXOType, UTXO } from "silent-payments";
3+
34
// Silent payment address generation using Diffie-Hellman
45
function generateSilentPaymentAddress(
56
recipientPublicKey: bitcoin.ECPairInterface,
67
senderPrivateKey: bitcoin.ECPairInterface
7-
): bitcoin.Address {
8-
// Diffie-Hellman shared secret (recipient's public key, sender's private key)
9-
const sharedSecret = bitcoin.crypto.sha256(
10-
bitcoin.ECPair.fromPublicKey(
11-
recipientPublicKey.publicKey
12-
).publicKey.mul(senderPrivateKey.privateKey!)
13-
);
8+
): string { // Changed return type from bitcoin.Address to string
9+
try {
10+
// Validate inputs
11+
if (!recipientPublicKey.publicKey) {
12+
throw new Error("Invalid recipient public key");
13+
}
14+
if (!senderPrivateKey.privateKey) {
15+
throw new Error("Invalid sender private key");
16+
}
17+
18+
// Diffie-Hellman shared secret (recipient's public key, sender's private key)
19+
const sharedSecret = bitcoin.crypto.sha256(
20+
recipientPublicKey.publicKey // .mul() not available on Buffer directly
21+
// Create temporary keypair for multiplication
22+
.constructor.fromPublicKey(recipientPublicKey.publicKey)
23+
.publicKey.mul(senderPrivateKey.privateKey)
24+
);
25+
26+
// Generate new stealth address using shared secret
27+
const newKeyPair = bitcoin.ECPair.makeRandom({ rng: () => sharedSecret });
28+
const { address } = bitcoin.payments.p2wpkh({
29+
pubkey: newKeyPair.publicKey,
30+
network: bitcoin.networks.bitcoin // Specify network explicitly
31+
});
1432

15-
// Generate new stealth address using shared secret
16-
const newKeyPair = bitcoin.ECPair.makeRandom({ rng: () => sharedSecret });
17-
const { address } = bitcoin.payments.p2wpkh({ pubkey: newKeyPair.publicKey });
33+
if (!address) {
34+
throw new Error("Failed to generate stealth address");
35+
}
1836

19-
return address!;
37+
return address;
38+
} catch (error) {
39+
throw new Error(`Silent payment address generation failed: ${error.message}`);
40+
}
2041
}
2142

2243
// Example usage of silent payment address generation
23-
const recipientKey = ECPair.fromPublicKey(/* recipient public key */);
24-
const senderKey = ECPair.fromWIF(/* sender private key */);
25-
const stealthAddress = generateSilentPaymentAddress(recipientKey, senderKey);
26-
27-
console.log("Stealth Address:", stealthAddress);
44+
try {
45+
const recipientKey = bitcoin.ECPair.makeRandom(); // For demo - replace with actual key
46+
const senderKey = bitcoin.ECPair.makeRandom(); // For demo - replace with actual key
47+
const stealthAddress = generateSilentPaymentAddress(recipientKey, senderKey);
48+
console.log("Stealth Address:", stealthAddress);
49+
} catch (error) {
50+
console.error(error.message);
51+
}
2852

2953
// Function to estimate the fee based on transaction size and fee rate
3054
function estimateTransactionFee(transactionSize: number, feeRate: number): number {
31-
return transactionSize * feeRate; // satoshis per byte
55+
if (transactionSize <= 0 || feeRate <= 0) {
56+
throw new Error("Invalid transaction size or fee rate");
57+
}
58+
return Math.ceil(transactionSize * feeRate); // Round up satoshis
59+
}
60+
61+
// Interface for transaction output
62+
interface TransactionOutput {
63+
address: string; // Changed from bitcoin.Address to string
64+
amount: number; // In satoshis
3265
}
3366

34-
// Allow users to set custom fee rates
3567
function createTransactionWithFee(
3668
selectedUTXOs: UTXO[],
37-
outputs: { address: bitcoin.Address; amount: number }[],
38-
feeRate: number
69+
outputs: TransactionOutput[],
70+
feeRate: number,
71+
changeAddress?: string // Optional change address parameter
3972
): bitcoin.Transaction {
40-
const txb = new bitcoin.TransactionBuilder();
41-
42-
let totalInputAmount = 0;
43-
for (const utxo of selectedUTXOs) {
44-
txb.addInput(utxo.txid, utxo.index);
45-
totalInputAmount += utxo.txout.value;
46-
}
73+
try {
74+
const txb = new bitcoin.TransactionBuilder();
75+
76+
// Validate inputs
77+
if (!selectedUTXOs.length) throw new Error("No UTXOs provided");
78+
if (!outputs.length) throw new Error("No outputs provided");
79+
if (feeRate <= 0) throw new Error("Invalid fee rate");
80+
81+
// Add inputs and calculate total
82+
let totalInputAmount = 0;
83+
for (const utxo of selectedUTXOs) {
84+
txb.addInput(utxo.txid, utxo.index);
85+
totalInputAmount += utxo.txout.value;
86+
}
4787

48-
let totalOutputAmount = outputs.reduce((sum, output) => sum + output.amount, 0);
88+
const totalOutputAmount = outputs.reduce((sum, output) => sum + output.amount, 0);
4989

50-
// Estimate transaction size (simplified, can adjust for more accuracy)
51-
const estimatedTxSize = selectedUTXOs.length * 180 + outputs.length * 34 + 10;
90+
// More accurate size estimation (vbytes)
91+
const estimatedTxSize =
92+
selectedUTXOs.length * 148 + // Inputs (P2PKH)
93+
outputs.length * 34 + // Outputs (P2WPKH)
94+
10 + // Base transaction overhead
95+
selectedUTXOs.length; // Witness data overhead
5296

53-
const fee = estimateTransactionFee(estimatedTxSize, feeRate);
97+
const fee = estimateTransactionFee(estimatedTxSize, feeRate);
5498

55-
// If inputs cover outputs and fee, add outputs
56-
if (totalInputAmount >= totalOutputAmount + fee) {
99+
// Validate funds
100+
if (totalInputAmount < totalOutputAmount + fee) {
101+
throw new Error(
102+
`Insufficient funds: ${totalInputAmount} available, ` +
103+
`${totalOutputAmount + fee} needed`
104+
);
105+
}
106+
107+
// Add outputs
57108
for (const { address, amount } of outputs) {
58109
txb.addOutput(address, amount);
59110
}
60111

61-
// Add change output (if needed)
112+
// Add change output if applicable
62113
const change = totalInputAmount - totalOutputAmount - fee;
63114
if (change > 0) {
64-
const changeAddress = /* user's change address */;
115+
if (!changeAddress) {
116+
throw new Error("Change address required for transaction with change");
117+
}
65118
txb.addOutput(changeAddress, change);
66119
}
67-
} else {
68-
throw new Error("Insufficient funds to cover the transaction fee.");
69-
}
70120

71-
return txb.buildIncomplete();
121+
return txb.buildIncomplete();
122+
} catch (error) {
123+
throw new Error(`Transaction creation failed: ${error.message}`);
124+
}
72125
}
73126

74127
// Example usage
75-
const feeRate = 20; // Satoshis per byte, chosen by the user from UI
76-
const transactionWithFee = createTransactionWithFee(selectedUTXOs, outputs, feeRate);
128+
try {
129+
const feeRate = 20; // Satoshis per byte
130+
const sampleUTXOs: UTXO[] = [
131+
// Replace with real UTXO data
132+
{ txid: "1234...", index: 0, txout: { value: 100000 } }
133+
];
134+
const sampleOutputs: TransactionOutput[] = [
135+
{ address: "bc1q...", amount: 50000 }
136+
];
137+
const changeAddress = "bc1q..."; // Add your change address
138+
139+
const transactionWithFee = createTransactionWithFee(
140+
sampleUTXOs,
141+
sampleOutputs,
142+
feeRate,
143+
changeAddress
144+
);
145+
console.log("Transaction created successfully");
146+
} catch (error) {
147+
console.error(error.message);
148+
}

0 commit comments

Comments
 (0)