Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions modules/sdk-coin-canton/src/canton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,23 @@ import {
TransactionType,
TssVerifyAddressOptions,
VerifyTransactionOptions,
TransactionExplanation as BaseTransactionExplanation,
BaseTransaction,
} from '@bitgo/sdk-core';
import { auditEddsaPrivateKey } from '@bitgo/sdk-lib-mpc';
import { BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics';
import { TransactionBuilderFactory } from './lib';
import { KeyPair as CantonKeyPair } from './lib/keyPair';
import utils from './lib/utils';

export interface TransactionExplanation extends BaseTransactionExplanation {
type: TransactionType;
}

export interface ExplainTransactionOptions {
txHex: string;
}

export class Canton extends BaseCoin {
protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;

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

private getBuilder(): TransactionBuilderFactory {
return new TransactionBuilderFactory(coins.get(this.getChain()));
}

/** @inheritDoc */
public getBaseFactor(): number {
return 1e10;
Expand Down Expand Up @@ -121,6 +135,20 @@ export class Canton extends BaseCoin {
};
}

/** @inheritDoc */
explainTransaction(params: ExplainTransactionOptions): Promise<TransactionExplanation> {
const factory = this.getBuilder();
let rebuiltTransaction: BaseTransaction;
const txRaw = params.txHex;
try {
const txBuilder = factory.from(txRaw);
rebuiltTransaction = txBuilder.transaction;
} catch (e) {
throw new Error('Invalid transaction');
}
return rebuiltTransaction.explainTransaction();
}

/** @inheritDoc */
isValidPub(pub: string): boolean {
return utils.isValidPublicKey(pub);
Expand Down
13 changes: 12 additions & 1 deletion modules/sdk-coin-canton/src/lib/iface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import { TransactionType } from '@bitgo/sdk-core';
import {
TransactionType,
TransactionExplanation as BaseTransactionExplanation,
ITransactionRecipient,
} from '@bitgo/sdk-core';
import { DamlTransaction, Metadata } from './resourcesInterface';

export interface TransactionExplanation extends BaseTransactionExplanation {
type: TransactionType;
inputs?: ITransactionRecipient[];
inputAmount?: string;
}

/**
* The transaction data returned from the toJson() function of a transaction
*/
Expand All @@ -9,6 +19,7 @@ export interface TxData {
type: TransactionType;
sender: string;
receiver: string;
amount: string;
acknowledgeData?: TransferAcknowledge;
}

Expand Down
48 changes: 47 additions & 1 deletion modules/sdk-coin-canton/src/lib/transaction/transaction.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { BaseKey, BaseTransaction, InvalidTransactionError, TransactionType } from '@bitgo/sdk-core';
import {
BaseKey,
BaseTransaction,
InvalidTransactionError,
ITransactionRecipient,
TransactionType,
} from '@bitgo/sdk-core';
import { BaseCoin as CoinConfig } from '@bitgo/statics';
import {
CantonPrepareCommandResponse,
MultiHashSignature,
PartySignature,
PreparedTxnParsedInfo,
TransactionBroadcastData,
TransactionExplanation,
TransferAcknowledge,
TxData,
} from '../iface';
Expand Down Expand Up @@ -127,6 +134,7 @@ export class Transaction extends BaseTransaction {
type: this._type as TransactionType,
sender: '',
receiver: '',
amount: '',
};
if (this._type === TransactionType.TransferAcknowledge) {
if (!this._acknowledgeData) {
Expand All @@ -147,6 +155,7 @@ export class Transaction extends BaseTransaction {
}
result.sender = parsedInfo.sender;
result.receiver = parsedInfo.receiver;
result.amount = parsedInfo.amount;
return result;
}

Expand Down Expand Up @@ -182,4 +191,41 @@ export class Transaction extends BaseTransaction {
throw new InvalidTransactionError('Unable to parse raw transaction data');
}
}

explainTransaction(): TransactionExplanation {
const displayOrder = [
'id',
'outputs',
'outputAmount',
'inputs',
'inputAmount',
'changeOutputs',
'changeAmount',
'fee',
'type',
];
const inputs: ITransactionRecipient[] = [];
let inputAmount = '0';
switch (this.type) {
case TransactionType.TransferAccept:
case TransactionType.TransferReject: {
const txData = this.toJson();
inputs.push({ address: txData.sender, amount: txData.amount });
inputAmount = txData.amount;
break;
}
}
return {
id: this.id,
displayOrder,
outputs: [],
outputAmount: '0',
inputs: inputs,
inputAmount: inputAmount,
changeOutputs: [],
changeAmount: '0',
fee: { fee: '0' },
type: this.type,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
MultiHashSignature,
OnboardingTransaction,
PreparedParty,
TransactionExplanation,
WalletInitBroadcastData,
WalletInitTxData,
} from '../iface';
Expand Down Expand Up @@ -97,4 +98,18 @@ export class WalletInitTransaction extends BaseTransaction {
throw new InvalidTransactionError('Unable to parse raw transaction data');
}
}

explainTransaction(): TransactionExplanation {
const displayOrder = ['id', 'outputs', 'outputAmount', 'changeOutputs', 'changeAmount', 'fee', 'type'];
return {
id: this.id,
displayOrder,
outputs: [],
outputAmount: '0',
changeOutputs: [],
changeAmount: '0',
fee: { fee: '0' },
type: this.type,
};
}
}
6 changes: 6 additions & 0 deletions modules/sdk-coin-canton/test/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { coins } from '@bitgo/statics';
import { TransactionBuilderFactory } from '../src';

export function getCantonBuilderFactory(coinName: string): TransactionBuilderFactory {
return new TransactionBuilderFactory(coins.get(coinName));
}
44 changes: 44 additions & 0 deletions modules/sdk-coin-canton/test/integration/canton.integration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import assert from 'assert';

import { TransactionType } from '@bitgo/sdk-core';

import { getCantonBuilderFactory } from '../helper';
import {
GenerateTopologyResponse,
TransferAcceptRawTransaction,
TransferRejectRawTransaction,
WalletInitRawTransaction,
} from '../resources';

describe('Canton integration tests', function () {
describe('Explain raw transaction', function () {
const factory = getCantonBuilderFactory('tcanton');
it('should explain raw wallet init transaction', function () {
const builder = factory.from(WalletInitRawTransaction);
const txn = builder.transaction;
const explainTxData = txn.explainTransaction();
assert(explainTxData);
assert.equal(explainTxData.id, GenerateTopologyResponse.multiHash);
assert.equal(explainTxData.type, TransactionType.WalletInitialization);
});

it('should explain raw transfer acceptance transaction', function () {
const builder = factory.from(TransferAcceptRawTransaction);
const txn = builder.transaction;
const explainTxData = txn.explainTransaction();
assert(explainTxData);
assert(explainTxData.id);
assert.equal(explainTxData.type, TransactionType.TransferAccept);
assert.equal(explainTxData.inputAmount, '5.0000000000');
});

it('should explain raw transfer rejection transaction', function () {
const builder = factory.from(TransferRejectRawTransaction);
const txn = builder.transaction;
const explainTxData = txn.explainTransaction();
assert(explainTxData);
assert.equal(explainTxData.type, TransactionType.TransferReject);
assert.equal(explainTxData.inputAmount, '5.0000000000');
});
});
});
12 changes: 10 additions & 2 deletions modules/sdk-coin-canton/test/resources.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe('Transfer Acceptance Builder', () => {
const txBuilder = new TransferAcceptanceBuilder(coins.get('tcanton'));
const transferAcceptanceTx = new Transaction(coins.get('tcanton'));
txBuilder.initBuilder(transferAcceptanceTx);
txBuilder.setTransaction(TransferAcceptancePrepareResponse);
const { commandId, contractId, partyId } = TransferAcceptance;
txBuilder.commandId(commandId).contractId(contractId).actAs(partyId);
const requestObj: CantonTransferAcceptRejectRequest = txBuilder.toRequestObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe('Transfer Rejection Builder', () => {
const txBuilder = new TransferRejectionBuilder(coins.get('tcanton'));
const tx = new Transaction(coins.get('tcanton'));
txBuilder.initBuilder(tx);
txBuilder.setTransaction(TransferRejectionPrepareResponse);
const { commandId, contractId, partyId } = TransferRejection;
txBuilder.commandId(commandId).contractId(contractId).actAs(partyId);
const requestObj: CantonTransferAcceptRejectRequest = txBuilder.toRequestObject();
Expand Down