Skip to content

Commit

Permalink
feat(sdk-coin-apt): addition of test case for apt transaction builder
Browse files Browse the repository at this point in the history
Ticket: COIN-2258
  • Loading branch information
baltiyal authored and bhavidhingra committed Jan 7, 2025
1 parent 6857221 commit ee1de61
Show file tree
Hide file tree
Showing 13 changed files with 756 additions and 146 deletions.
91 changes: 86 additions & 5 deletions modules/sdk-coin-apt/src/apt.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
BaseCoin,
BaseTransaction,
BitGoBase,
InvalidAddressError,
KeyPair,
Expand All @@ -11,9 +12,17 @@ import {
VerifyAddressOptions,
VerifyTransactionOptions,
} from '@bitgo/sdk-core';
import { BaseCoin as StaticsBaseCoin } from '@bitgo/statics';
import { KeyPair as AptKeyPair } from './lib';
import { BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics';
import { KeyPair as AptKeyPair, TransactionBuilderFactory, TransferTransaction } from './lib';
import utils from './lib/utils';
import * as _ from 'lodash';
import BigNumber from 'bignumber.js';
import { ExplainTransactionOptions } from './lib/types';
import { AptTransactionExplanation } from './lib/iface';

export interface AptParseTransactionOptions extends ParseTransactionOptions {
txHex: string;
}

export class Apt extends BaseCoin {
protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;
Expand Down Expand Up @@ -64,7 +73,40 @@ export class Apt extends BaseCoin {
}

async verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
throw new Error('Method not implemented.');
const coinConfig = coins.get(this.getChain());
const { txPrebuild: txPrebuild, txParams: txParams } = params;
const transaction = new TransferTransaction(coinConfig);
const rawTx = txPrebuild.txHex;
if (!rawTx) {
throw new Error('missing required tx prebuild property txHex');
}
transaction.fromRawTransaction(rawTx);
const explainedTx = transaction.explainTransaction();
if (txParams.recipients !== undefined) {
const filteredRecipients = txParams.recipients?.map((recipient) => {
return {
address: recipient.address, // TODO: check this
amount: BigInt(recipient.amount),
};
});
const filteredOutputs = explainedTx.outputs.map((output) => {
return {
address: output.address,
amount: BigInt(output.amount),
};
});
if (!_.isEqual(filteredOutputs, filteredRecipients)) {
throw new Error('Tx outputs does not match with expected txParams recipients');
}
let totalAmount = new BigNumber(0);
for (const recipients of txParams.recipients) {
totalAmount = totalAmount.plus(recipients.amount);
}
if (!totalAmount.isEqualTo(explainedTx.outputAmount)) {
throw new Error('Tx total amount does not match with expected total amount field');
}
}
return true;
}

async isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
Expand All @@ -76,8 +118,43 @@ export class Apt extends BaseCoin {
return true;
}

parseTransaction(params: ParseTransactionOptions): Promise<ParsedTransaction> {
throw new Error('Method not implemented.');
async parseTransaction(params: AptParseTransactionOptions): Promise<ParsedTransaction> {
const transactionExplanation = await this.explainTransaction({ txHex: params.txHex });
if (!transactionExplanation) {
throw new Error('Invalid transaction');
}
return {
inputs: [
{
address: transactionExplanation.sender,
amount: transactionExplanation.outputAmount,
},
],
outputs: [
{
address: transactionExplanation.outputs[0].address,
amount: transactionExplanation.outputs[0].amount,
},
],
};
}

/**
* Explain a Apt transaction
* @param params
*/
async explainTransaction(params: ExplainTransactionOptions): Promise<AptTransactionExplanation> {
const factory = this.getBuilder();
let rebuiltTransaction: BaseTransaction;

try {
const transactionBuilder = factory.from(params.txHex);
rebuiltTransaction = await transactionBuilder.build();
} catch {
throw new Error('Invalid transaction');
}

return rebuiltTransaction.explainTransaction();
}

generateKeyPair(seed?: Buffer): KeyPair {
Expand All @@ -103,4 +180,8 @@ export class Apt extends BaseCoin {
signTransaction(params: SignTransactionOptions): Promise<SignedTransaction> {
throw new Error('Method not implemented.');
}

private getBuilder(): TransactionBuilderFactory {
return new TransactionBuilderFactory(coins.get(this.getChain()));
}
}
31 changes: 15 additions & 16 deletions modules/sdk-coin-apt/src/lib/iface.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import { ITransactionExplanation, TransactionFee } from '@bitgo/sdk-core';
import {
TransactionExplanation as BaseTransactionExplanation,
TransactionRecipient,
TransactionType as BitGoTransactionType,
} from '@bitgo/sdk-core';

export type TransactionExplanation = ITransactionExplanation<TransactionFee>;
export interface AptTransactionExplanation extends BaseTransactionExplanation {
sender?: string;
type?: BitGoTransactionType;
}

/**
* The transaction data returned from the toJson() function of a transaction
*/
export interface TxData {
export interface TransferTxData {
id: string;
sender: string;
sequenceNumber: bigint;
maxGasAmount: bigint;
gasUnitPrice: bigint;
expirationTime: bigint;
payload: AptPayload;
chainId: number;
}

export interface AptPayload {
function: string;
typeArguments: string[];
arguments: string[];
type: string;
recipient: TransactionRecipient;
sequenceNumber: number;
maxGasAmount: number;
gasUnitPrice: number;
expirationTime: number;
}
Loading

0 comments on commit ee1de61

Please sign in to comment.