Skip to content

Commit

Permalink
Merge pull request #1953 from aeternity/feature/fixes
Browse files Browse the repository at this point in the history
Fixes around `sendTransaction`
  • Loading branch information
davidyuk authored Mar 4, 2024
2 parents b70554e + d9cde12 commit 48ee661
Show file tree
Hide file tree
Showing 21 changed files with 227 additions and 178 deletions.
6 changes: 3 additions & 3 deletions src/AeSdkMethods.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as chainMethods from './chain';
import { sendTransaction } from './send-transaction';
import * as aensMethods from './aens';
import * as spendMethods from './spend';
import * as oracleMethods from './oracle';
Expand All @@ -15,10 +16,9 @@ import CompilerBase from './contract/compiler/Base';

export type OnAccount = Encoded.AccountAddress | AccountBase | undefined;

const { InvalidTxError: _2, ...chainMethodsOther } = chainMethods;

const methods = {
...chainMethodsOther,
...chainMethods,
sendTransaction,
...aensMethods,
...spendMethods,
...oracleMethods,
Expand Down
3 changes: 2 additions & 1 deletion src/aens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import { commitmentHash, isAuctionName } from './tx/builder/helpers';
import { Tag, AensName, ConsensusProtocolVersion } from './tx/builder/constants';
import { Encoded, Encoding } from './utils/encoder';
import { UnsupportedProtocolError } from './utils/errors';
import { sendTransaction, SendTransactionOptions, getName } from './chain';
import { getName } from './chain';
import { sendTransaction, SendTransactionOptions } from './send-transaction';
import { buildTxAsync, BuildTxOptions } from './tx/builder';
import { TransformNodeType } from './Node';
import { NameEntry, NamePointer } from './apis/node';
Expand Down
133 changes: 3 additions & 130 deletions src/chain.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { AE_AMOUNT_FORMATS, formatAmount } from './utils/amount-formatter';
import verifyTransaction, { ValidatorResult } from './tx/validator';
import {
ensureError, isAccountNotFoundError, pause, unwrapProxy,
} from './utils/other';
import { isAccountNotFoundError, pause, unwrapProxy } from './utils/other';
import { isNameValid, produceNameId } from './tx/builder/helpers';
import { DRY_RUN_ACCOUNT } from './tx/builder/schema';
import { AensName } from './tx/builder/constants';
import { AensName, DRY_RUN_ACCOUNT } from './tx/builder/constants';
import {
AensPointerContextError, DryRunError, InvalidAensNameError, TransactionError,
AensPointerContextError, DryRunError, InvalidAensNameError,
TxTimedOutError, TxNotInChainError, InternalError,
} from './utils/errors';
import Node, { TransformNodeType } from './Node';
Expand All @@ -18,8 +14,6 @@ import {
import {
decode, encode, Encoded, Encoding,
} from './utils/encoder';
import AccountBase from './account/Base';
import { buildTxHash } from './tx/builder';

/**
* @category chain
Expand All @@ -38,26 +32,6 @@ export function _getPollInterval(
return Math.floor(base / 3);
}

/**
* @category exception
*/
export class InvalidTxError extends TransactionError {
validation: ValidatorResult[];

transaction: Encoded.Transaction;

constructor(
message: string,
validation: ValidatorResult[],
transaction: Encoded.Transaction,
) {
super(message);
this.name = 'InvalidTxError';
this.validation = validation;
this.transaction = transaction;
}
}

const heightCache: WeakMap<Node, { time: number; height: number }> = new WeakMap();

/**
Expand Down Expand Up @@ -164,107 +138,6 @@ export async function waitForTxConfirm(
}
}

/**
* Signs and submits transaction for mining
* @category chain
* @param txUnsigned - Transaction to sign and submit
* @param options - Options
* @returns Transaction details
*/
export async function sendTransaction(
txUnsigned: Encoded.Transaction,
{
onNode, onAccount, verify = true, waitMined = true, confirm, innerTx, ...options
}:
SendTransactionOptions,
): Promise<SendTransactionReturnType> {
const tx = await onAccount.signTransaction(txUnsigned, {
...options,
onNode,
innerTx,
networkId: await onNode.getNetworkId(),
});

if (innerTx === true) return { hash: buildTxHash(tx), rawTx: tx };

if (verify) {
const validation = await verifyTransaction(tx, onNode);
if (validation.length > 0) {
const message = `Transaction verification errors: ${
validation.map((v: { message: string }) => v.message).join(', ')}`;
throw new InvalidTxError(message, validation, tx);
}
}

try {
let __queue;
try {
__queue = onAccount != null ? `tx-${onAccount.address}` : null;
} catch (error) {
__queue = null;
}
const { txHash } = await onNode.postTransaction(
{ tx },
__queue != null ? { requestOptions: { customHeaders: { __queue } } } : {},
);

if (waitMined) {
const pollResult = await poll(txHash, { onNode, ...options });
const txData = {
...pollResult,
hash: pollResult.hash as Encoded.TxHash,
rawTx: tx,
};
// wait for transaction confirmation
if (confirm != null && +confirm > 0) {
const c = typeof confirm === 'boolean' ? undefined : confirm;
return {
...txData,
confirmationHeight: await waitForTxConfirm(txHash, { onNode, confirm: c, ...options }),
};
}
return txData;
}
return { hash: txHash, rawTx: tx };
} catch (error) {
ensureError(error);
throw Object.assign(error, {
rawTx: tx,
verifyTx: async () => verifyTransaction(tx, onNode),
});
}
}

type SendTransactionOptionsType = {
/**
* Node to use
*/
onNode: Node;
/**
* Account to use
*/
onAccount: AccountBase;
/**
* Verify transaction before broadcast, throw error if not
*/
verify?: boolean;
/**
* Ensure that transaction get into block
*/
waitMined?: boolean;
/**
* Number of micro blocks that should be mined after tx get included
*/
confirm?: boolean | number;
} & Parameters<typeof poll>[1] & Omit<Parameters<typeof waitForTxConfirm>[1], 'confirm'>
& Parameters<AccountBase['signTransaction']>[1];
export interface SendTransactionOptions extends SendTransactionOptionsType {}
interface SendTransactionReturnType extends Partial<TransformNodeType<SignedTx>> {
hash: Encoded.TxHash;
rawTx: Encoded.Transaction;
confirmationHeight?: number;
}

/**
* Get account by account public key
* @category chain
Expand Down
11 changes: 6 additions & 5 deletions src/contract/Contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
*/

import { Encoder as Calldata } from '@aeternity/aepp-calldata';
import { DRY_RUN_ACCOUNT } from '../tx/builder/schema';
import { Tag, AensName, ConsensusProtocolVersion } from '../tx/builder/constants';
import {
Tag, AensName, ConsensusProtocolVersion, DRY_RUN_ACCOUNT,
} from '../tx/builder/constants';
import {
buildContractIdByContractTx, unpackTx, buildTxAsync, BuildTxOptions, buildTxHash,
} from '../tx/builder';
Expand Down Expand Up @@ -39,9 +40,9 @@ import {
import CompilerBase, { Aci } from './compiler/Base';
import Node, { TransformNodeType } from '../Node';
import {
getAccount, getContract, getContractByteCode, resolveName, txDryRun, sendTransaction,
SendTransactionOptions,
getAccount, getContract, getContractByteCode, resolveName, txDryRun,
} from '../chain';
import { sendTransaction, SendTransactionOptions } from '../send-transaction';
import AccountBase from '../account/Base';
import { TxUnpacked } from '../tx/builder/schema.generated';
import { isAccountNotFoundError } from '../utils/other';
Expand Down Expand Up @@ -259,7 +260,7 @@ class Contract<M extends ContractMethodsBase> {
'init',
{ ...opt, onAccount: opt.onAccount },
);
this.$options.address = buildContractIdByContractTx(tx);
this.$options.address = buildContractIdByContractTx(other.rawTx);
return {
...other,
...other.result?.log != null && {
Expand Down
5 changes: 3 additions & 2 deletions src/contract/ga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import { concatBuffers } from '../utils/other';
import AccountBase from '../account/Base';
import Contract from './Contract';
import Node from '../Node';
import { sendTransaction, SendTransactionOptions, getAccount } from '../chain';
import { getAccount } from '../chain';
import { sendTransaction, SendTransactionOptions } from '../send-transaction';
import CompilerBase from './compiler/Base';

/**
Expand Down Expand Up @@ -57,10 +58,10 @@ export async function createGeneralizedAccount(
callData: contract._calldata.encode(contract._name, 'init', args),
authFun: hash(authFnName),
});
const contractId = buildContractIdByContractTx(tx);
const { hash: transaction, rawTx } = await sendTransaction(tx, {
onNode, onAccount, onCompiler, ...options,
});
const contractId = buildContractIdByContractTx(rawTx);

return Object.freeze({
owner: ownerId,
Expand Down
7 changes: 4 additions & 3 deletions src/index-browser.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
export {
_getPollInterval, InvalidTxError, getHeight, poll, awaitHeight, waitForTxConfirm, sendTransaction,
_getPollInterval, getHeight, poll, awaitHeight, waitForTxConfirm,
getAccount, getBalance, getCurrentGeneration, getGeneration, getMicroBlockTransactions,
getKeyBlock, getMicroBlockHeader, txDryRun, getContractByteCode, getContract, getName,
resolveName,
} from './chain';
export { InvalidTxError, sendTransaction } from './send-transaction';
export {
getAddressFromPriv, isAddressValid, genSalt, encodeUnsigned, hash, encodeContractAddress,
generateKeyPairFromSecret, generateKeyPair, sign, verify, messageToHash, signMessage,
Expand All @@ -22,11 +23,11 @@ export {
export {
MAX_AUTH_FUN_GAS, MIN_GAS_PRICE,
NAME_FEE_MULTIPLIER, NAME_FEE_BID_INCREMENT, NAME_BID_TIMEOUT_BLOCKS, NAME_MAX_LENGTH_FEE,
NAME_BID_RANGES, ConsensusProtocolVersion, VmVersion, AbiVersion, Tag,
NAME_BID_RANGES, ConsensusProtocolVersion, VmVersion, AbiVersion, Tag, DRY_RUN_ACCOUNT,
} from './tx/builder/constants';
export type { Int, AensName } from './tx/builder/constants';
// TODO: move to constants
export { ORACLE_TTL_TYPES, DRY_RUN_ACCOUNT, CallReturnType } from './tx/builder/schema';
export { ORACLE_TTL_TYPES, CallReturnType } from './tx/builder/schema';
export { DelegationTag } from './tx/builder/delegation/schema';
export { packDelegation, unpackDelegation } from './tx/builder/delegation';
export {
Expand Down
5 changes: 2 additions & 3 deletions src/oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ import { RequestTimedOutError } from './utils/errors';
import {
decode, encode, Encoded, Encoding,
} from './utils/encoder';
import {
_getPollInterval, getHeight, sendTransaction, SendTransactionOptions,
} from './chain';
import { _getPollInterval, getHeight } from './chain';
import { sendTransaction, SendTransactionOptions } from './send-transaction';
import Node from './Node';
import AccountBase from './account/Base';

Expand Down
Loading

0 comments on commit 48ee661

Please sign in to comment.