Skip to content

Commit

Permalink
add internal transaction submission file
Browse files Browse the repository at this point in the history
  • Loading branch information
0xmaayan committed Oct 11, 2023
1 parent 1819e03 commit ed12f27
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 98 deletions.
46 changes: 7 additions & 39 deletions src/api/transaction_submission.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { AptosConfig } from "./aptos_config";
import { Account } from "../core/account";
import { AccountAuthenticator } from "../transactions/authenticator/account";
import { MimeType, postAptosFullNode } from "../client";
import {
AnyRawTransaction,
GenerateMultiAgentRawTransactionInput,
Expand All @@ -15,12 +14,11 @@ import {
} from "../transactions/types";
import { UserTransactionResponse, PendingTransactionResponse } from "../types";
import {
generateSignedTransaction,
generateSignedTransactionForSimulation,
generateTransaction,
generateTransactionPayload,
signTransaction,
} from "../transactions/transaction_builder/transaction_builder";
simulateTransaction,
submitTransaction,
} from "../internal/transaction_submission";

export class TransactionSubmission {
readonly config: AptosConfig;
Expand Down Expand Up @@ -81,17 +79,8 @@ export class TransactionSubmission {
* ```
*/
async generateTransaction(args: GenerateTransactionInput): Promise<AnyRawTransaction> {
const { sender, data, options, secondarySignerAddresses, feePayerAddress } = args;
const payload = await generateTransactionPayload(data);
const rawTransaction = await generateTransaction({
aptosConfig: this.config,
sender,
payload,
options,
secondarySignerAddresses,
feePayerAddress,
});
return rawTransaction;
const transaction = await generateTransaction({ aptosConfig: this.config, ...args });
return transaction;
}

/**
Expand Down Expand Up @@ -125,21 +114,7 @@ export class TransactionSubmission {
* @param options optional. A config to simulate the transaction with
*/
async simulateTransaction(args: SimulateTransactionData): Promise<Array<UserTransactionResponse>> {
const signedTransaction = generateSignedTransactionForSimulation({
...args,
});
const { data } = await postAptosFullNode<Uint8Array, Array<UserTransactionResponse>>({
aptosConfig: this.config,
body: signedTransaction,
path: "transactions/simulate",
params: {
estimate_gas_unit_price: args.options?.estimateGasUnitPrice ?? false,
estimate_max_gas_amount: args.options?.estimateMaxGasAmount ?? false,
estimate_prioritized_gas_unit_price: args.options?.estimatePrioritizedGasUnitPrice ?? false,
},
originMethod: "simulateTransaction",
contentType: MimeType.BCS_SIGNED_TRANSACTION,
});
const data = await simulateTransaction({ aptosConfig: this.config, ...args });
return data;
}

Expand All @@ -160,14 +135,7 @@ export class TransactionSubmission {
additionalSignersAuthenticators?: Array<AccountAuthenticator>;
};
}): Promise<PendingTransactionResponse> {
const signedTransaction = generateSignedTransaction({ ...args });
const { data } = await postAptosFullNode<Uint8Array, PendingTransactionResponse>({
aptosConfig: this.config,
body: signedTransaction,
path: "transactions",
originMethod: "submitTransaction",
contentType: MimeType.BCS_SIGNED_TRANSACTION,
});
const data = await submitTransaction({ aptosConfig: this.config, ...args });
return data;
}
}
4 changes: 2 additions & 2 deletions src/client/core.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import aptosClient from "@aptos-labs/aptos-client";
import { AptosApiError, AptosResponse, MimeType } from "./types";
import { AptosApiError, AptosResponse } from "./types";
import { VERSION } from "../version";
import { ClientConfig, AptosRequest } from "../types";
import { ClientConfig, AptosRequest, MimeType } from "../types";
import { AptosConfig } from "../api/aptos_config";

/**
Expand Down
4 changes: 2 additions & 2 deletions src/client/get.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AptosResponse, MimeType } from "./types";
import { AptosResponse } from "./types";
import { aptosRequest } from "./core";
import { AnyNumber, ClientConfig } from "../types";
import { AnyNumber, ClientConfig, MimeType } from "../types";
import { AptosConfig } from "../api/aptos_config";
import { AptosApiType } from "../utils/const";

Expand Down
4 changes: 2 additions & 2 deletions src/client/post.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AptosConfig } from "../api/aptos_config";
import { AnyNumber, ClientConfig } from "../types";
import { AnyNumber, ClientConfig, MimeType } from "../types";
import { aptosRequest } from "./core";
import { AptosResponse, MimeType } from "./types";
import { AptosResponse } from "./types";
import { AptosApiType } from "../utils/const";

export type PostRequestOptions = {
Expand Down
15 changes: 0 additions & 15 deletions src/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,3 @@ export class AptosApiError extends Error {
this.request = request;
}
}

export enum MimeType {
/**
* JSON representation, used for transaction submission and accept type JSON output
*/
JSON = "application/json",
/**
* BCS representation, used for accept type BCS output
*/
BCS = "application/x-bcs",
/**
* BCS representation, used for transaction submission in BCS input
*/
BCS_SIGNED_TRANSACTION = "application/x.aptos.signed_transaction+bcs",
}
163 changes: 163 additions & 0 deletions src/internal/transaction_submission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/**
* This file contains the underlying implementations for exposed API surface in
* the {@link api/transaction_submission}. By moving the methods out into a separate file,
* other namespaces and processes can access these methods without depending on the entire
* transaction_submission namespace and without having a dependency cycle error.
*/

import { AptosConfig } from "../api/aptos_config";
import { postAptosFullNode } from "../client";
import { Account } from "../core/account";
import { AccountAuthenticator } from "../transactions/authenticator/account";
import {
buildTransaction,
generateTransactionPayload,
generateSignedTransactionForSimulation,
generateSignedTransaction,
sign,
} from "../transactions/transaction_builder/transaction_builder";
import { GenerateTransactionInput, AnyRawTransaction, SimulateTransactionData } from "../transactions/types";
import { UserTransactionResponse, PendingTransactionResponse, MimeType } from "../types";

/**
* Generates any transaction by passing in the required arguments
*
* @param args.sender The transaction sender's account address as a HexInput
* @param args.data EntryFunctionData | ScriptData | MultiSigData
* @param feePayerAddress optional. For a fee payer (aka sponsored) transaction
* @param secondarySignerAddresses optional. For a multi agent or fee payer (aka sponsored) transactions
* @param args.options optional. GenerateTransactionOptions type
*
* @example
* For a single signer entry function
* move function name, move function type arguments, move function arguments
* `
* data: {
* function:"0x1::aptos_account::transfer",
* type_arguments:[]
* arguments:[recieverAddress,10]
* }
* `
*
* @example
* For a single signer script function
* module bytecode, move function type arguments, move function arguments
* ```
* data: {
* bytecode:"0x001234567",
* type_arguments:[],
* arguments:[recieverAddress,10]
* }
* ```
*
* @return A raw transaction type (note that it holds the raw transaction as a bcs serialized data)
* ```
* {
* rawTransaction: Uint8Array,
* secondarySignerAddresses? : Array<AccountAddress>,
* feePayerAddress?: AccountAddress
* }
* ```
*/
export async function generateTransaction(
args: { aptosConfig: AptosConfig } & GenerateTransactionInput,
): Promise<AnyRawTransaction> {
const { aptosConfig, sender, data, options, secondarySignerAddresses, feePayerAddress } = args;
const payload = await generateTransactionPayload(data);
const rawTransaction = await buildTransaction({
aptosConfig,
sender,
payload,
options,
secondarySignerAddresses,
feePayerAddress,
});
return rawTransaction;
}

/**
* Sign a transaction that can later be submitted to chain
*
* @param args.signer The signer account to sign the transaction
* @param args.transaction A raw transaction type (note that it holds the raw transaction as a bcs serialized data)
* ```
* {
* rawTransaction: Uint8Array,
* secondarySignerAddresses? : Array<AccountAddress>,
* feePayerAddress?: AccountAddress
* }
* ```
*
* @return The signer AccountAuthenticator
*/
export function signTransaction(args: { signer: Account; transaction: AnyRawTransaction }): AccountAuthenticator {
const accountAuthenticator = sign({ ...args });
return accountAuthenticator;
}

/**
* Simulates a transaction before singing it.
*
* @param signerPublicKey The signer pubic key
* @param transaction The raw transaction to simulate
* @param secondarySignersPublicKeys optional. For when the transaction is a multi signers transaction
* @param feePayerPublicKey optional. For when the transaction is a fee payer (aka sponsored) transaction
* @param options optional. A config to simulate the transaction with
*/
export async function simulateTransaction(
args: { aptosConfig: AptosConfig } & SimulateTransactionData,
): Promise<Array<UserTransactionResponse>> {
const { aptosConfig, transaction, signerPublicKey, secondarySignersPublicKeys, feePayerPublicKey, options } = args;

const signedTransaction = generateSignedTransactionForSimulation({
transaction,
signerPublicKey,
secondarySignersPublicKeys,
feePayerPublicKey,
options,
});

const { data } = await postAptosFullNode<Uint8Array, Array<UserTransactionResponse>>({
aptosConfig,
body: signedTransaction,
path: "transactions/simulate",
params: {
estimate_gas_unit_price: args.options?.estimateGasUnitPrice ?? false,
estimate_max_gas_amount: args.options?.estimateMaxGasAmount ?? false,
estimate_prioritized_gas_unit_price: args.options?.estimatePrioritizedGasUnitPrice ?? false,
},
originMethod: "simulateTransaction",
contentType: MimeType.BCS_SIGNED_TRANSACTION,
});
return data;
}

/**
* Submit transaction to chain
*
* @param args.transaction A aptos transaction type
* @param args.senderAuthenticator The account authenticator of the transaction sender
* @param args.secondarySignerAuthenticators optional. For when the transaction is a multi signers transaction
*
* @return PendingTransactionResponse
*/
export async function submitTransaction(args: {
aptosConfig: AptosConfig;
transaction: AnyRawTransaction;
senderAuthenticator: AccountAuthenticator;
secondarySignerAuthenticators?: {
feePayerAuthenticator?: AccountAuthenticator;
additionalSignersAuthenticators?: Array<AccountAuthenticator>;
};
}): Promise<PendingTransactionResponse> {
const { aptosConfig } = args;
const signedTransaction = generateSignedTransaction({ ...args });
const { data } = await postAptosFullNode<Uint8Array, PendingTransactionResponse>({
aptosConfig,
body: signedTransaction,
path: "transactions",
originMethod: "submitTransaction",
contentType: MimeType.BCS_SIGNED_TRANSACTION,
});
return data;
}
34 changes: 20 additions & 14 deletions src/transactions/transaction_builder/transaction_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import { getLedgerInfo } from "../../internal/general";
import { getGasPriceEstimation } from "../../internal/transaction";
import { HexInput, SigningScheme } from "../../types";
import { NetworkToChainId } from "../../utils/api-endpoints";
import { DEFAULT_MAX_GAS_AMOUNT, DEFAULT_TXN_EXP_SEC_FROM_NOW } from "../../utils/const";
import {
DEFAULT_MAX_GAS_AMOUNT,
DEFAULT_TXN_EXP_SEC_FROM_NOW,
RAW_TRANSACTION_SALT,
RAW_TRANSACTION_WITH_DATA_SALT,
} from "../../utils/const";
import {
AccountAuthenticator,
AccountAuthenticatorEd25519,
Expand Down Expand Up @@ -177,12 +182,10 @@ export async function generateRawTransaction(args: {
* When we call our `generateTransaction` function with the relevant type properties,
* Typescript can infer the return type based on the appropriate function overload.
*/
export async function generateTransaction(
args: GenerateSingleSignerRawTransactionArgs,
): Promise<SingleSignerTransaction>;
export async function generateTransaction(args: GenerateFeePayerRawTransactionArgs): Promise<FeePayerTransaction>;
export async function generateTransaction(args: GenerateMultiAgentRawTransactionArgs): Promise<MultiAgentTransaction>;
export async function generateTransaction(args: GenerateRawTransactionArgs): Promise<AnyRawTransaction>;
export async function buildTransaction(args: GenerateSingleSignerRawTransactionArgs): Promise<SingleSignerTransaction>;
export async function buildTransaction(args: GenerateFeePayerRawTransactionArgs): Promise<FeePayerTransaction>;
export async function buildTransaction(args: GenerateMultiAgentRawTransactionArgs): Promise<MultiAgentTransaction>;
export async function buildTransaction(args: GenerateRawTransactionArgs): Promise<AnyRawTransaction>;
/**
* Generates a transaction based on the provided arguments
*
Expand All @@ -205,7 +208,7 @@ export async function generateTransaction(args: GenerateRawTransactionArgs): Pro
* }
* ```
*/
export async function generateTransaction(args: GenerateRawTransactionArgs): Promise<AnyRawTransaction> {
export async function buildTransaction(args: GenerateRawTransactionArgs): Promise<AnyRawTransaction> {
const { aptosConfig, sender, payload, options, secondarySignerAddresses, feePayerAddress } = args;
// generate raw transaction
const rawTxn = await generateRawTransaction({
Expand Down Expand Up @@ -243,8 +246,14 @@ export async function generateTransaction(args: GenerateRawTransactionArgs): Pro

/**
* Simluate a transaction before signing and submit to chain
* @param args
* @returns
*
* @param args.transaction A aptos transaction type to sign
* @param args.signerPublicKey The signer public key
* @param args.secondarySignersPublicKeys optional. The secondart signers public keys if multi signers transaction
* @param args.feePayerPublicKey optional. The fee payer public key is a fee payer (aka sponsored) transaction
* @param args.options optional. SimulateTransactionOptions
*
* @returns A signed serialized transaction that can be simulated
*/
export function generateSignedTransactionForSimulation(args: SimulateTransactionData): Uint8Array {
const { signerPublicKey, transaction, secondarySignersPublicKeys, feePayerPublicKey } = args;
Expand Down Expand Up @@ -337,7 +346,7 @@ export function generateSignedTransactionForSimulation(args: SimulateTransaction
*
* @return The signer AccountAuthenticator
*/
export function signTransaction(args: { signer: Account; transaction: AnyRawTransaction }): AccountAuthenticator {
export function sign(args: { signer: Account; transaction: AnyRawTransaction }): AccountAuthenticator {
const { signer, transaction } = args;

const transactionToSign = deriveTransactionType(transaction);
Expand Down Expand Up @@ -502,9 +511,6 @@ export function generateMultiSignersSignedTransaction(
);
}

const RAW_TRANSACTION_SALT = "APTOS::RawTransaction";
const RAW_TRANSACTION_WITH_DATA_SALT = "APTOS::RawTransactionWithData";

export function getSigningMessage(rawTxn: AnyRawTransactionInstance): Uint8Array {
const hash = sha3Hash.create();

Expand Down
15 changes: 15 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@ import { Network } from "../utils/api-endpoints";

export * from "./indexer";

export enum MimeType {
/**
* JSON representation, used for transaction submission and accept type JSON output
*/
JSON = "application/json",
/**
* BCS representation, used for accept type BCS output
*/
BCS = "application/x-bcs",
/**
* BCS representation, used for transaction submission in BCS input
*/
BCS_SIGNED_TRANSACTION = "application/x.aptos.signed_transaction+bcs",
}

/**
* Hex data as input to a function
*/
Expand Down
3 changes: 3 additions & 0 deletions src/utils/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ export enum AptosApiType {
export const DEFAULT_MAX_GAS_AMOUNT = 200000;
// Transaction expire timestamp
export const DEFAULT_TXN_EXP_SEC_FROM_NOW = 20;
export const APTOS_COIN = "0x1::aptos_coin::AptosCoin";
export const RAW_TRANSACTION_SALT = "APTOS::RawTransaction";
export const RAW_TRANSACTION_WITH_DATA_SALT = "APTOS::RawTransactionWithData";
Loading

0 comments on commit ed12f27

Please sign in to comment.