Skip to content

Commit

Permalink
feat(sdk-coin-apt): transaction builder for aptos
Browse files Browse the repository at this point in the history
TICKET: COIN-2258
  • Loading branch information
bhavidhingra committed Jan 11, 2025
1 parent fe9db91 commit 660e37a
Show file tree
Hide file tree
Showing 19 changed files with 1,268 additions and 58 deletions.
6 changes: 4 additions & 2 deletions modules/sdk-coin-apt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@
"@aptos-labs/ts-sdk": "^1.32.0",
"@bitgo/sdk-core": "^28.19.0",
"@bitgo/statics": "^50.18.0",
"bignumber.js": "^9.1.2"
"bignumber.js": "^9.1.2",
"lodash": "^4.17.21"
},
"devDependencies": {
"@bitgo/sdk-api": "^1.58.0",
"@bitgo/sdk-test": "^8.0.63"
"@bitgo/sdk-test": "^8.0.63",
"@bitgo/sdk-lib-mpc": "^10.1.0"
}
}
89 changes: 84 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,
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,41 @@ 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 | undefined> {
const factory = this.getBuilder();
let rebuiltTransaction: BaseTransaction;
try {
const transactionBuilder = factory.from(params.txHex);
rebuiltTransaction = await transactionBuilder.build();
} catch {
return undefined;
}
return rebuiltTransaction.explainTransaction();
}

generateKeyPair(seed?: Buffer): KeyPair {
Expand All @@ -103,4 +178,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()));
}
}
3 changes: 3 additions & 0 deletions modules/sdk-coin-apt/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ export const APT_ADDRESS_LENGTH = 64;
export const APT_TRANSACTION_ID_LENGTH = 64;
export const APT_BLOCK_ID_LENGTH = 64;
export const APT_SIGNATURE_LENGTH = 128;
export const UNAVAILABLE_TEXT = 'UNAVAILABLE';
export const DEFAULT_GAS_UNIT_PRICE = 100;
export const SECONDS_PER_WEEK = 7 * 24 * 60 * 60; // Days * Hours * Minutes * Seconds
19 changes: 18 additions & 1 deletion modules/sdk-coin-apt/src/lib/iface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
import {
TransactionExplanation as BaseTransactionExplanation,
TransactionRecipient,
TransactionType as BitGoTransactionType,
} from '@bitgo/sdk-core';

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;
recipient: TransactionRecipient;
sequenceNumber: number;
maxGasAmount: number;
gasUnitPrice: number;
expirationTime: number;
}
3 changes: 2 additions & 1 deletion modules/sdk-coin-apt/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import * as Utils from './utils';
import * as Interface from './iface';

export { KeyPair } from './keyPair';
export { Transaction } from './transaction';
export { Transaction } from './transaction/transaction';
export { TransferTransaction } from './transaction/transferTransaction';
export { TransactionBuilder } from './transactionBuilder';
export { TransferBuilder } from './transferBuilder';
export { TransactionBuilderFactory } from './transactionBuilderFactory';
Expand Down
16 changes: 0 additions & 16 deletions modules/sdk-coin-apt/src/lib/transaction.ts

This file was deleted.

Loading

0 comments on commit 660e37a

Please sign in to comment.