-
Notifications
You must be signed in to change notification settings - Fork 62
/
Copy pathtxOut.ts
100 lines (87 loc) · 3.38 KB
/
txOut.ts
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
91
92
93
94
95
96
97
98
99
100
import * as Trezor from '@trezor/connect';
import { Cardano, Serialization } from '@cardano-sdk/core';
import { GroupedAddress, util } from '@cardano-sdk/key-management';
import { HexBlob, InvalidArgumentError, Transform } from '@cardano-sdk/util';
import { TrezorTxOutputDestination, TrezorTxTransformerContext } from '../types';
import { mapTokenMap } from './assets';
const toDestination: Transform<Cardano.TxOut, TrezorTxOutputDestination, TrezorTxTransformerContext> = (
txOut,
context
) => {
const knownAddress = context?.knownAddresses.find((address: GroupedAddress) => address.address === txOut.address);
const isScriptAddress = Cardano.util.isScriptAddress(txOut.address);
if (!knownAddress || isScriptAddress) {
return {
address: txOut.address
};
}
const paymentPath = util.paymentKeyPathFromGroupedAddress(knownAddress);
const stakingPath = util.stakeKeyPathFromGroupedAddress(knownAddress);
if (!stakingPath) throw new InvalidArgumentError('txOut', 'Missing staking key key path.');
return {
addressParameters: {
addressType: Trezor.PROTO.CardanoAddressType.BASE,
path: paymentPath,
stakingPath
}
};
};
const getScriptHex = (output: Serialization.TransactionOutput): HexBlob | undefined => {
const scriptRef = output.scriptRef();
if (!scriptRef) return undefined;
return scriptRef.toCbor();
};
/**
* There are currently two types of outputs supported by the ledger:
*
* legacy_transaction_output =
* [ address
* , amount : value
* , ? datum_hash : $hash32
* ]
*
* and
*
* post_alonzo_transaction_output =
* { 0 : address
* , 1 : value
* , ? 2 : datum_option ; New; datum option
* , ? 3 : script_ref ; New; script reference
* }
*
* Legacy outputs are definite length arrays of three elements, however the new babbage outputs are definite length maps
* of four elements.
*
* @param out The output to be verified.
*/
const isBabbage = (out: Serialization.TransactionOutput): boolean => {
const reader = new Serialization.CborReader(out.toCbor());
return reader.peekState() === Serialization.CborReaderState.StartMap;
};
const getInlineDatum = (datum: Cardano.PlutusData): string => Serialization.PlutusData.fromCore(datum).toCbor();
export const toTxOut: Transform<Cardano.TxOut, Trezor.CardanoOutput, TrezorTxTransformerContext> = (txOut, context) => {
const destination = toDestination(txOut, context);
const output = Serialization.TransactionOutput.fromCore(txOut);
const scriptHex = getScriptHex(output);
return isBabbage(output)
? {
...destination,
amount: txOut.value.coins.toString(),
datumHash: txOut.datumHash?.toString(),
format: Trezor.PROTO.CardanoTxOutputSerializationFormat.MAP_BABBAGE,
inlineDatum: txOut.datum ? getInlineDatum(txOut.datum) : undefined,
referenceScript: scriptHex,
tokenBundle: mapTokenMap(txOut.value.assets)
}
: {
...destination,
amount: txOut.value.coins.toString(),
datumHash: txOut.datumHash?.toString(),
format: Trezor.PROTO.CardanoTxOutputSerializationFormat.ARRAY_LEGACY,
inlineDatum: undefined,
referenceScript: undefined,
tokenBundle: mapTokenMap(txOut.value.assets)
};
};
export const mapTxOuts = (txOuts: Cardano.TxOut[], context: TrezorTxTransformerContext): Trezor.CardanoOutput[] =>
txOuts.map((txOut) => toTxOut(txOut, context));