Skip to content

Commit ec683b8

Browse files
authored
Merge pull request #7377 from BitGo/COIN-6230
feat: added explainTransaction for canton
2 parents fc5dc2b + 080a847 commit ec683b8

File tree

9 files changed

+164
-4
lines changed

9 files changed

+164
-4
lines changed

modules/sdk-coin-canton/src/canton.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,23 @@ import {
1313
TransactionType,
1414
TssVerifyAddressOptions,
1515
VerifyTransactionOptions,
16+
TransactionExplanation as BaseTransactionExplanation,
17+
BaseTransaction,
1618
} from '@bitgo/sdk-core';
1719
import { auditEddsaPrivateKey } from '@bitgo/sdk-lib-mpc';
1820
import { BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics';
1921
import { TransactionBuilderFactory } from './lib';
2022
import { KeyPair as CantonKeyPair } from './lib/keyPair';
2123
import utils from './lib/utils';
2224

25+
export interface TransactionExplanation extends BaseTransactionExplanation {
26+
type: TransactionType;
27+
}
28+
29+
export interface ExplainTransactionOptions {
30+
txHex: string;
31+
}
32+
2333
export class Canton extends BaseCoin {
2434
protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;
2535

@@ -37,6 +47,10 @@ export class Canton extends BaseCoin {
3747
return new Canton(bitgo, staticsCoin);
3848
}
3949

50+
private getBuilder(): TransactionBuilderFactory {
51+
return new TransactionBuilderFactory(coins.get(this.getChain()));
52+
}
53+
4054
/** @inheritDoc */
4155
public getBaseFactor(): number {
4256
return 1e10;
@@ -121,6 +135,20 @@ export class Canton extends BaseCoin {
121135
};
122136
}
123137

138+
/** @inheritDoc */
139+
explainTransaction(params: ExplainTransactionOptions): Promise<TransactionExplanation> {
140+
const factory = this.getBuilder();
141+
let rebuiltTransaction: BaseTransaction;
142+
const txRaw = params.txHex;
143+
try {
144+
const txBuilder = factory.from(txRaw);
145+
rebuiltTransaction = txBuilder.transaction;
146+
} catch (e) {
147+
throw new Error('Invalid transaction');
148+
}
149+
return rebuiltTransaction.explainTransaction();
150+
}
151+
124152
/** @inheritDoc */
125153
isValidPub(pub: string): boolean {
126154
return utils.isValidPublicKey(pub);

modules/sdk-coin-canton/src/lib/iface.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
1-
import { TransactionType } from '@bitgo/sdk-core';
1+
import {
2+
TransactionType,
3+
TransactionExplanation as BaseTransactionExplanation,
4+
ITransactionRecipient,
5+
} from '@bitgo/sdk-core';
26
import { DamlTransaction, Metadata } from './resourcesInterface';
37

8+
export interface TransactionExplanation extends BaseTransactionExplanation {
9+
type: TransactionType;
10+
inputs?: ITransactionRecipient[];
11+
inputAmount?: string;
12+
}
13+
414
/**
515
* The transaction data returned from the toJson() function of a transaction
616
*/
@@ -9,6 +19,7 @@ export interface TxData {
919
type: TransactionType;
1020
sender: string;
1121
receiver: string;
22+
amount: string;
1223
acknowledgeData?: TransferAcknowledge;
1324
}
1425

modules/sdk-coin-canton/src/lib/transaction/transaction.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1-
import { BaseKey, BaseTransaction, InvalidTransactionError, TransactionType } from '@bitgo/sdk-core';
1+
import {
2+
BaseKey,
3+
BaseTransaction,
4+
InvalidTransactionError,
5+
ITransactionRecipient,
6+
TransactionType,
7+
} from '@bitgo/sdk-core';
28
import { BaseCoin as CoinConfig } from '@bitgo/statics';
39
import {
410
CantonPrepareCommandResponse,
511
MultiHashSignature,
612
PartySignature,
713
PreparedTxnParsedInfo,
814
TransactionBroadcastData,
15+
TransactionExplanation,
916
TransferAcknowledge,
1017
TxData,
1118
} from '../iface';
@@ -127,6 +134,7 @@ export class Transaction extends BaseTransaction {
127134
type: this._type as TransactionType,
128135
sender: '',
129136
receiver: '',
137+
amount: '',
130138
};
131139
if (this._type === TransactionType.TransferAcknowledge) {
132140
if (!this._acknowledgeData) {
@@ -147,6 +155,7 @@ export class Transaction extends BaseTransaction {
147155
}
148156
result.sender = parsedInfo.sender;
149157
result.receiver = parsedInfo.receiver;
158+
result.amount = parsedInfo.amount;
150159
return result;
151160
}
152161

@@ -182,4 +191,41 @@ export class Transaction extends BaseTransaction {
182191
throw new InvalidTransactionError('Unable to parse raw transaction data');
183192
}
184193
}
194+
195+
explainTransaction(): TransactionExplanation {
196+
const displayOrder = [
197+
'id',
198+
'outputs',
199+
'outputAmount',
200+
'inputs',
201+
'inputAmount',
202+
'changeOutputs',
203+
'changeAmount',
204+
'fee',
205+
'type',
206+
];
207+
const inputs: ITransactionRecipient[] = [];
208+
let inputAmount = '0';
209+
switch (this.type) {
210+
case TransactionType.TransferAccept:
211+
case TransactionType.TransferReject: {
212+
const txData = this.toJson();
213+
inputs.push({ address: txData.sender, amount: txData.amount });
214+
inputAmount = txData.amount;
215+
break;
216+
}
217+
}
218+
return {
219+
id: this.id,
220+
displayOrder,
221+
outputs: [],
222+
outputAmount: '0',
223+
inputs: inputs,
224+
inputAmount: inputAmount,
225+
changeOutputs: [],
226+
changeAmount: '0',
227+
fee: { fee: '0' },
228+
type: this.type,
229+
};
230+
}
185231
}

modules/sdk-coin-canton/src/lib/walletInitialization/walletInitTransaction.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
MultiHashSignature,
55
OnboardingTransaction,
66
PreparedParty,
7+
TransactionExplanation,
78
WalletInitBroadcastData,
89
WalletInitTxData,
910
} from '../iface';
@@ -97,4 +98,18 @@ export class WalletInitTransaction extends BaseTransaction {
9798
throw new InvalidTransactionError('Unable to parse raw transaction data');
9899
}
99100
}
101+
102+
explainTransaction(): TransactionExplanation {
103+
const displayOrder = ['id', 'outputs', 'outputAmount', 'changeOutputs', 'changeAmount', 'fee', 'type'];
104+
return {
105+
id: this.id,
106+
displayOrder,
107+
outputs: [],
108+
outputAmount: '0',
109+
changeOutputs: [],
110+
changeAmount: '0',
111+
fee: { fee: '0' },
112+
type: this.type,
113+
};
114+
}
100115
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { coins } from '@bitgo/statics';
2+
import { TransactionBuilderFactory } from '../src';
3+
4+
export function getCantonBuilderFactory(coinName: string): TransactionBuilderFactory {
5+
return new TransactionBuilderFactory(coins.get(coinName));
6+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import assert from 'assert';
2+
3+
import { TransactionType } from '@bitgo/sdk-core';
4+
5+
import { getCantonBuilderFactory } from '../helper';
6+
import {
7+
GenerateTopologyResponse,
8+
TransferAcceptRawTransaction,
9+
TransferRejectRawTransaction,
10+
WalletInitRawTransaction,
11+
} from '../resources';
12+
13+
describe('Canton integration tests', function () {
14+
describe('Explain raw transaction', function () {
15+
const factory = getCantonBuilderFactory('tcanton');
16+
it('should explain raw wallet init transaction', function () {
17+
const builder = factory.from(WalletInitRawTransaction);
18+
const txn = builder.transaction;
19+
const explainTxData = txn.explainTransaction();
20+
assert(explainTxData);
21+
assert.equal(explainTxData.id, GenerateTopologyResponse.multiHash);
22+
assert.equal(explainTxData.type, TransactionType.WalletInitialization);
23+
});
24+
25+
it('should explain raw transfer acceptance transaction', function () {
26+
const builder = factory.from(TransferAcceptRawTransaction);
27+
const txn = builder.transaction;
28+
const explainTxData = txn.explainTransaction();
29+
assert(explainTxData);
30+
assert(explainTxData.id);
31+
assert.equal(explainTxData.type, TransactionType.TransferAccept);
32+
assert.equal(explainTxData.inputAmount, '5.0000000000');
33+
});
34+
35+
it('should explain raw transfer rejection transaction', function () {
36+
const builder = factory.from(TransferRejectRawTransaction);
37+
const txn = builder.transaction;
38+
const explainTxData = txn.explainTransaction();
39+
assert(explainTxData);
40+
assert.equal(explainTxData.type, TransactionType.TransferReject);
41+
assert.equal(explainTxData.inputAmount, '5.0000000000');
42+
});
43+
});
44+
});

modules/sdk-coin-canton/test/resources.ts

Lines changed: 10 additions & 2 deletions
Large diffs are not rendered by default.

modules/sdk-coin-canton/test/unit/builder/transferAccept/transferAcceptBuilder.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ describe('Transfer Acceptance Builder', () => {
1313
const txBuilder = new TransferAcceptanceBuilder(coins.get('tcanton'));
1414
const transferAcceptanceTx = new Transaction(coins.get('tcanton'));
1515
txBuilder.initBuilder(transferAcceptanceTx);
16+
txBuilder.setTransaction(TransferAcceptancePrepareResponse);
1617
const { commandId, contractId, partyId } = TransferAcceptance;
1718
txBuilder.commandId(commandId).contractId(contractId).actAs(partyId);
1819
const requestObj: CantonTransferAcceptRejectRequest = txBuilder.toRequestObject();

modules/sdk-coin-canton/test/unit/builder/transferReject/transferRejectBuilder.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ describe('Transfer Rejection Builder', () => {
1313
const txBuilder = new TransferRejectionBuilder(coins.get('tcanton'));
1414
const tx = new Transaction(coins.get('tcanton'));
1515
txBuilder.initBuilder(tx);
16+
txBuilder.setTransaction(TransferRejectionPrepareResponse);
1617
const { commandId, contractId, partyId } = TransferRejection;
1718
txBuilder.commandId(commandId).contractId(contractId).actAs(partyId);
1819
const requestObj: CantonTransferAcceptRejectRequest = txBuilder.toRequestObject();

0 commit comments

Comments
 (0)