-
Notifications
You must be signed in to change notification settings - Fork 302
Expand file tree
/
Copy pathexplainPsbtWasm.ts
More file actions
90 lines (76 loc) · 3.19 KB
/
explainPsbtWasm.ts
File metadata and controls
90 lines (76 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import { fixedScriptWallet } from '@bitgo/wasm-utxo';
import { Triple } from '@bitgo/sdk-core';
import type { FixedScriptWalletOutput, Output } from '../types';
import type { TransactionExplanationWasm } from './explainTransaction';
function scriptToAddress(script: Uint8Array): string {
return `scriptPubKey:${Buffer.from(script).toString('hex')}`;
}
type ParsedWalletOutput = fixedScriptWallet.ParsedOutput & { scriptId: fixedScriptWallet.ScriptId };
type ParsedExternalOutput = fixedScriptWallet.ParsedOutput & { scriptId: null };
function isParsedWalletOutput(output: ParsedWalletOutput | ParsedExternalOutput): output is ParsedWalletOutput {
return output.scriptId !== null;
}
function isParsedExternalOutput(output: ParsedWalletOutput | ParsedExternalOutput): output is ParsedExternalOutput {
return output.scriptId === null;
}
function toChangeOutput(output: ParsedWalletOutput): FixedScriptWalletOutput {
return {
address: output.address ?? scriptToAddress(output.script),
amount: output.value.toString(),
chain: output.scriptId.chain,
index: output.scriptId.index,
external: false,
};
}
function toExternalOutput(output: ParsedExternalOutput): Output {
return {
address: output.address ?? scriptToAddress(output.script),
amount: output.value.toString(),
external: true,
};
}
export function explainPsbtWasm(
psbt: fixedScriptWallet.BitGoPsbt,
walletXpubs: Triple<string> | fixedScriptWallet.RootWalletKeys,
params: {
replayProtection: {
checkSignature?: boolean;
publicKeys: Buffer[];
};
customChangeWalletXpubs?: Triple<string> | fixedScriptWallet.RootWalletKeys;
}
): TransactionExplanationWasm {
const parsed = psbt.parseTransactionWithWalletKeys(walletXpubs, { replayProtection: params.replayProtection });
const changeOutputs: FixedScriptWalletOutput[] = [];
const outputs: Output[] = [];
const parsedCustomChangeOutputs = params.customChangeWalletXpubs
? psbt.parseOutputsWithWalletKeys(params.customChangeWalletXpubs)
: undefined;
const customChangeOutputs: FixedScriptWalletOutput[] = [];
parsed.outputs.forEach((output, i) => {
const parseCustomChangeOutput = parsedCustomChangeOutputs?.[i];
if (isParsedWalletOutput(output)) {
// This is a change output
changeOutputs.push(toChangeOutput(output));
} else if (parseCustomChangeOutput && isParsedWalletOutput(parseCustomChangeOutput)) {
customChangeOutputs.push(toChangeOutput(parseCustomChangeOutput));
} else if (isParsedExternalOutput(output)) {
outputs.push(toExternalOutput(output));
} else {
throw new Error('Invalid output');
}
});
const outputAmount = outputs.reduce((sum, output) => sum + BigInt(output.amount), BigInt(0));
const changeAmount = changeOutputs.reduce((sum, output) => sum + BigInt(output.amount), BigInt(0));
const customChangeAmount = customChangeOutputs.reduce((sum, output) => sum + BigInt(output.amount), BigInt(0));
return {
id: psbt.unsignedTxId(),
outputAmount: outputAmount.toString(),
changeAmount: changeAmount.toString(),
customChangeAmount: customChangeAmount.toString(),
outputs,
changeOutputs,
customChangeOutputs,
fee: parsed.minerFee.toString(),
};
}