|
1 | 1 | import BigNumber from 'bignumber.js'; |
2 | 2 | import crypto from 'crypto'; |
3 | 3 |
|
4 | | -import { BaseUtils, isValidEd25519PublicKey } from '@bitgo/sdk-core'; |
| 4 | +import { BaseUtils, isValidEd25519PublicKey, TransactionType } from '@bitgo/sdk-core'; |
5 | 5 |
|
6 | 6 | import { computePreparedTransaction } from '../../resources/hash/hash.js'; |
7 | 7 | import { PreparedTransaction } from '../../resources/proto/preparedTransaction.js'; |
@@ -79,66 +79,102 @@ export class Utils implements BaseUtils { |
79 | 79 | /** |
80 | 80 | * Method to parse raw canton transaction & get required data |
81 | 81 | * @param {String} rawData base64 encoded string |
| 82 | + * @param {TransactionType} txType the transaction type |
82 | 83 | * @returns {PreparedTxnParsedInfo} |
83 | 84 | */ |
84 | | - parseRawCantonTransactionData(rawData: string): PreparedTxnParsedInfo { |
| 85 | + parseRawCantonTransactionData(rawData: string, txType: TransactionType): PreparedTxnParsedInfo { |
85 | 86 | const decodedData = this.decodePreparedTransaction(rawData); |
86 | 87 | let sender = ''; |
87 | 88 | let receiver = ''; |
88 | 89 | let amount = ''; |
89 | | - decodedData.transaction?.nodes?.forEach((node) => { |
| 90 | + let preApprovalNode: RecordField[] = []; |
| 91 | + let transferNode: RecordField[] = []; |
| 92 | + let transferAcceptRejectNode: RecordField[] = []; |
| 93 | + const nodes = decodedData.transaction?.nodes; |
| 94 | + |
| 95 | + nodes?.forEach((node) => { |
90 | 96 | const versionedNode = node.versionedNode; |
91 | 97 | if (!versionedNode || versionedNode.oneofKind !== 'v1') return; |
92 | | - |
93 | 98 | const v1Node = versionedNode.v1; |
94 | 99 | const nodeType = v1Node.nodeType; |
95 | | - |
96 | 100 | if (nodeType.oneofKind !== 'create') return; |
97 | | - |
98 | 101 | const createNode = nodeType.create; |
99 | | - |
100 | | - const getField = (fields: RecordField[], label: string) => fields.find((f) => f.label === label)?.value?.sum; |
101 | | - |
102 | | - // Check if it's the correct template |
103 | 102 | const template = createNode.templateId; |
104 | 103 | const argSum = createNode.argument?.sum; |
105 | 104 | if (!argSum || argSum.oneofKind !== 'record') return; |
106 | 105 | const fields = argSum.record?.fields; |
107 | 106 | if (!fields) return; |
108 | | - if (template?.entityName === 'AmuletTransferInstruction') { |
109 | | - const transferField = fields.find((f) => f.label === 'transfer'); |
110 | | - const transferSum = transferField?.value?.sum; |
111 | | - if (!transferSum || transferSum.oneofKind !== 'record') return; |
| 107 | + if ( |
| 108 | + template?.entityName === 'TransferPreapprovalProposal' && |
| 109 | + !preApprovalNode.length && |
| 110 | + txType === TransactionType.OneStepPreApproval |
| 111 | + ) { |
| 112 | + preApprovalNode = fields; |
| 113 | + } |
| 114 | + if ( |
| 115 | + template?.entityName === 'Amulet' && |
| 116 | + node?.nodeId === '9' && |
| 117 | + !transferAcceptRejectNode.length && |
| 118 | + txType === TransactionType.TransferAccept |
| 119 | + ) { |
| 120 | + transferAcceptRejectNode = fields; |
| 121 | + } |
| 122 | + if ( |
| 123 | + template?.entityName === 'Amulet' && |
| 124 | + node?.nodeId === '4' && |
| 125 | + !transferAcceptRejectNode.length && |
| 126 | + txType === TransactionType.TransferReject |
| 127 | + ) { |
| 128 | + transferAcceptRejectNode = fields; |
| 129 | + } |
| 130 | + if ( |
| 131 | + template?.entityName === 'AmuletTransferInstruction' && |
| 132 | + node?.nodeId === '14' && |
| 133 | + !transferNode.length && |
| 134 | + txType === TransactionType.Send |
| 135 | + ) { |
| 136 | + transferNode = fields; |
| 137 | + } |
| 138 | + }); |
| 139 | + |
| 140 | + const getField = (fields: RecordField[], label: string) => fields.find((f) => f.label === label)?.value?.sum; |
| 141 | + |
| 142 | + if (preApprovalNode.length) { |
| 143 | + const receiverData = getField(preApprovalNode, 'receiver'); |
| 144 | + if (receiverData?.oneofKind === 'party') receiver = receiverData.party ?? ''; |
| 145 | + const providerData = getField(preApprovalNode, 'provider'); |
| 146 | + if (providerData?.oneofKind === 'party') sender = providerData.party ?? ''; |
| 147 | + amount = '0'; |
| 148 | + } else if (transferNode.length) { |
| 149 | + const transferField = transferNode.find((f) => f.label === 'transfer'); |
| 150 | + const transferSum = transferField?.value?.sum; |
| 151 | + if (transferSum && transferSum.oneofKind === 'record') { |
112 | 152 | const transferRecord = transferSum.record?.fields; |
113 | | - if (!transferRecord) return; |
114 | | - const senderData = getField(transferRecord, 'sender'); |
115 | | - if (senderData?.oneofKind === 'party') sender = senderData.party ?? ''; |
116 | | - |
117 | | - const receiverData = getField(transferRecord, 'receiver'); |
118 | | - if (receiverData?.oneofKind === 'party') receiver = receiverData.party ?? ''; |
119 | | - |
120 | | - const amountData = getField(transferRecord, 'amount'); |
121 | | - if (amountData?.oneofKind === 'numeric') amount = amountData.numeric ?? ''; |
122 | | - } else if (template?.entityName === 'Amulet') { |
123 | | - const dsoData = getField(fields, 'dso'); |
124 | | - if (dsoData?.oneofKind === 'party') sender = dsoData.party ?? ''; |
125 | | - const ownerData = getField(fields, 'owner'); |
126 | | - if (ownerData?.oneofKind === 'party') receiver = ownerData.party ?? ''; |
127 | | - const amountField = getField(fields, 'amount'); |
128 | | - if (!amountField || amountField.oneofKind !== 'record') return; |
| 153 | + if (transferRecord?.length) { |
| 154 | + const senderData = getField(transferRecord, 'sender'); |
| 155 | + if (senderData?.oneofKind === 'party') sender = senderData.party ?? ''; |
129 | 156 |
|
| 157 | + const receiverData = getField(transferRecord, 'receiver'); |
| 158 | + if (receiverData?.oneofKind === 'party') receiver = receiverData.party ?? ''; |
| 159 | + |
| 160 | + const amountData = getField(transferRecord, 'amount'); |
| 161 | + if (amountData?.oneofKind === 'numeric') amount = amountData.numeric ?? ''; |
| 162 | + } |
| 163 | + } |
| 164 | + } else if (transferAcceptRejectNode.length) { |
| 165 | + const dsoData = getField(transferAcceptRejectNode, 'dso'); |
| 166 | + if (dsoData?.oneofKind === 'party') sender = dsoData.party ?? ''; |
| 167 | + const ownerData = getField(transferAcceptRejectNode, 'owner'); |
| 168 | + if (ownerData?.oneofKind === 'party') receiver = ownerData.party ?? ''; |
| 169 | + const amountField = getField(transferAcceptRejectNode, 'amount'); |
| 170 | + if (amountField && amountField.oneofKind === 'record') { |
130 | 171 | const amountRecord = amountField.record?.fields; |
131 | | - if (!amountRecord) return; |
132 | | - const initialAmountData = getField(amountRecord, 'initialAmount'); |
133 | | - if (initialAmountData?.oneofKind === 'numeric') amount = initialAmountData.numeric ?? ''; |
134 | | - } else if (template?.entityName === 'TransferPreapprovalProposal') { |
135 | | - const receiverData = getField(fields, 'receiver'); |
136 | | - if (receiverData?.oneofKind === 'party') receiver = receiverData.party ?? ''; |
137 | | - const providerData = getField(fields, 'provider'); |
138 | | - if (providerData?.oneofKind === 'party') sender = providerData.party ?? ''; |
139 | | - amount = '0'; |
| 172 | + if (amountRecord?.length) { |
| 173 | + const initialAmountData = getField(amountRecord, 'initialAmount'); |
| 174 | + if (initialAmountData?.oneofKind === 'numeric') amount = initialAmountData.numeric ?? ''; |
| 175 | + } |
140 | 176 | } |
141 | | - }); |
| 177 | + } |
142 | 178 | if (!sender || !receiver || !amount) { |
143 | 179 | const missingFields: string[] = []; |
144 | 180 | if (!sender) missingFields.push('sender'); |
|
0 commit comments