Skip to content

Commit 7c5bb07

Browse files
authored
Merge pull request #5318 from BitGo/coin-2258-apt-tx-builder-1
feat(sdk-coin-apt): transaction builder
2 parents b2d29ea + 660e37a commit 7c5bb07

File tree

18 files changed

+1265
-55
lines changed

18 files changed

+1265
-55
lines changed

modules/sdk-coin-apt/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@
4343
"@aptos-labs/ts-sdk": "^1.32.0",
4444
"@bitgo/sdk-core": "^28.19.0",
4545
"@bitgo/statics": "^50.18.0",
46-
"bignumber.js": "^9.1.2"
46+
"bignumber.js": "^9.1.2",
47+
"lodash": "^4.17.21"
4748
},
4849
"devDependencies": {
4950
"@bitgo/sdk-api": "^1.58.0",
50-
"@bitgo/sdk-test": "^8.0.63"
51+
"@bitgo/sdk-test": "^8.0.63",
52+
"@bitgo/sdk-lib-mpc": "^10.1.0"
5153
}
5254
}

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

Lines changed: 84 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
BaseCoin,
3+
BaseTransaction,
34
BitGoBase,
45
InvalidAddressError,
56
KeyPair,
@@ -11,9 +12,17 @@ import {
1112
VerifyAddressOptions,
1213
VerifyTransactionOptions,
1314
} from '@bitgo/sdk-core';
14-
import { BaseCoin as StaticsBaseCoin } from '@bitgo/statics';
15-
import { KeyPair as AptKeyPair } from './lib';
15+
import { BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics';
16+
import { KeyPair as AptKeyPair, TransactionBuilderFactory, TransferTransaction } from './lib';
1617
import utils from './lib/utils';
18+
import * as _ from 'lodash';
19+
import BigNumber from 'bignumber.js';
20+
import { ExplainTransactionOptions } from './lib/types';
21+
import { AptTransactionExplanation } from './lib/iface';
22+
23+
export interface AptParseTransactionOptions extends ParseTransactionOptions {
24+
txHex: string;
25+
}
1726

1827
export class Apt extends BaseCoin {
1928
protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;
@@ -64,7 +73,40 @@ export class Apt extends BaseCoin {
6473
}
6574

6675
async verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
67-
throw new Error('Method not implemented.');
76+
const coinConfig = coins.get(this.getChain());
77+
const { txPrebuild: txPrebuild, txParams: txParams } = params;
78+
const transaction = new TransferTransaction(coinConfig);
79+
const rawTx = txPrebuild.txHex;
80+
if (!rawTx) {
81+
throw new Error('missing required tx prebuild property txHex');
82+
}
83+
transaction.fromRawTransaction(rawTx);
84+
const explainedTx = transaction.explainTransaction();
85+
if (txParams.recipients !== undefined) {
86+
const filteredRecipients = txParams.recipients?.map((recipient) => {
87+
return {
88+
address: recipient.address,
89+
amount: BigInt(recipient.amount),
90+
};
91+
});
92+
const filteredOutputs = explainedTx.outputs.map((output) => {
93+
return {
94+
address: output.address,
95+
amount: BigInt(output.amount),
96+
};
97+
});
98+
if (!_.isEqual(filteredOutputs, filteredRecipients)) {
99+
throw new Error('Tx outputs does not match with expected txParams recipients');
100+
}
101+
let totalAmount = new BigNumber(0);
102+
for (const recipients of txParams.recipients) {
103+
totalAmount = totalAmount.plus(recipients.amount);
104+
}
105+
if (!totalAmount.isEqualTo(explainedTx.outputAmount)) {
106+
throw new Error('Tx total amount does not match with expected total amount field');
107+
}
108+
}
109+
return true;
68110
}
69111

70112
async isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
@@ -76,8 +118,41 @@ export class Apt extends BaseCoin {
76118
return true;
77119
}
78120

79-
parseTransaction(params: ParseTransactionOptions): Promise<ParsedTransaction> {
80-
throw new Error('Method not implemented.');
121+
async parseTransaction(params: AptParseTransactionOptions): Promise<ParsedTransaction> {
122+
const transactionExplanation = await this.explainTransaction({ txHex: params.txHex });
123+
if (!transactionExplanation) {
124+
throw new Error('Invalid transaction');
125+
}
126+
return {
127+
inputs: [
128+
{
129+
address: transactionExplanation.sender,
130+
amount: transactionExplanation.outputAmount,
131+
},
132+
],
133+
outputs: [
134+
{
135+
address: transactionExplanation.outputs[0].address,
136+
amount: transactionExplanation.outputs[0].amount,
137+
},
138+
],
139+
};
140+
}
141+
142+
/**
143+
* Explain a Apt transaction
144+
* @param params
145+
*/
146+
async explainTransaction(params: ExplainTransactionOptions): Promise<AptTransactionExplanation | undefined> {
147+
const factory = this.getBuilder();
148+
let rebuiltTransaction: BaseTransaction;
149+
try {
150+
const transactionBuilder = factory.from(params.txHex);
151+
rebuiltTransaction = await transactionBuilder.build();
152+
} catch {
153+
return undefined;
154+
}
155+
return rebuiltTransaction.explainTransaction();
81156
}
82157

83158
generateKeyPair(seed?: Buffer): KeyPair {
@@ -103,4 +178,8 @@ export class Apt extends BaseCoin {
103178
signTransaction(params: SignTransactionOptions): Promise<SignedTransaction> {
104179
throw new Error('Method not implemented.');
105180
}
181+
182+
private getBuilder(): TransactionBuilderFactory {
183+
return new TransactionBuilderFactory(coins.get(this.getChain()));
184+
}
106185
}

modules/sdk-coin-apt/src/lib/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@ export const APT_ADDRESS_LENGTH = 64;
22
export const APT_TRANSACTION_ID_LENGTH = 64;
33
export const APT_BLOCK_ID_LENGTH = 64;
44
export const APT_SIGNATURE_LENGTH = 128;
5+
export const UNAVAILABLE_TEXT = 'UNAVAILABLE';
6+
export const DEFAULT_GAS_UNIT_PRICE = 100;
7+
export const SECONDS_PER_WEEK = 7 * 24 * 60 * 60; // Days * Hours * Minutes * Seconds
Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
1+
import {
2+
TransactionExplanation as BaseTransactionExplanation,
3+
TransactionRecipient,
4+
TransactionType as BitGoTransactionType,
5+
} from '@bitgo/sdk-core';
6+
7+
export interface AptTransactionExplanation extends BaseTransactionExplanation {
8+
sender?: string;
9+
type?: BitGoTransactionType;
10+
}
11+
112
/**
213
* The transaction data returned from the toJson() function of a transaction
314
*/
4-
export interface TxData {
15+
export interface TransferTxData {
516
id: string;
17+
sender: string;
18+
recipient: TransactionRecipient;
19+
sequenceNumber: number;
20+
maxGasAmount: number;
21+
gasUnitPrice: number;
22+
expirationTime: number;
623
}

modules/sdk-coin-apt/src/lib/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import * as Utils from './utils';
22
import * as Interface from './iface';
33

44
export { KeyPair } from './keyPair';
5-
export { Transaction } from './transaction';
5+
export { Transaction } from './transaction/transaction';
6+
export { TransferTransaction } from './transaction/transferTransaction';
67
export { TransactionBuilder } from './transactionBuilder';
78
export { TransferBuilder } from './transferBuilder';
89
export { TransactionBuilderFactory } from './transactionBuilderFactory';

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

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)