Skip to content

Commit

Permalink
refactor: rename addMissingVariables to estimateTxDependencies, a…
Browse files Browse the repository at this point in the history
…dd docs (FuelLabs#954)
  • Loading branch information
Dhaiwat10 authored Apr 30, 2023
1 parent dadc576 commit bf6214c
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 31 deletions.
7 changes: 7 additions & 0 deletions .changeset/funny-balloons-cheat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"docs": minor
"@fuel-ts/providers": minor
"@fuel-ts/wallet": minor
---

The `addMissingVariable` helper has been renamed to `estimateTxDependencies`, and some documentation around it has been added.
4 changes: 4 additions & 0 deletions apps/docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ export default defineConfig({
text: 'Variables Outputs',
link: '/guide/contracts/variable-outputs',
},
{
text: 'Transaction Dependency Estimation',
link: '/guide/contracts/transaction-dependency-estimation',
},
{
text: 'The Fuelvm Binary File',
link: '/guide/contracts/the-fuelvm-binary-file',
Expand Down
11 changes: 11 additions & 0 deletions apps/docs/src/guide/contracts/transaction-dependency-estimation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Transaction Dependency Estimation

[Previously](./variable-outputs.md), we mentioned that a contract call might require you to manually specify external contracts or variable outputs.

However, the SDK always automatically estimates these dependencies and double-checks if everything is in order whenever you invoke a contract function or attempt to send a transaction.

The SDK uses the `estimateTxDependencies` helper function to set any missing dependencies identified during the estimation process. This requires simulating the transaction a few times in the background.

<<< @/../../../packages/providers/src/provider.ts#Provider-sendTransaction{ts:line-numbers}

While relying on the SDK's automatic estimation is a decent default behavior, we recommend manually specifying the dependencies if they are known in advance to avoid the performance impact of the estimation process.
38 changes: 23 additions & 15 deletions packages/providers/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,15 +281,18 @@ export default class Provider {
}

/**
* Submits a transaction to the chain to be executed
* If the transaction is missing VariableOuputs
* the transaction will be mutate and VariableOuputs will be added
* Submits a transaction to the chain to be executed.
*
* If the transaction is missing any dependencies,
* the transaction will be mutated and those dependencies will be added
*/
// #region Provider-sendTransaction
async sendTransaction(
transactionRequestLike: TransactionRequestLike
): Promise<TransactionResponse> {
const transactionRequest = transactionRequestify(transactionRequestLike);
await this.addMissingVariables(transactionRequest);
await this.estimateTxDependencies(transactionRequest);
// #endregion Provider-sendTransaction

const encodedTransaction = hexlify(transactionRequest.toTransactionBytes());
const { gasUsed, minGasPrice } = await this.getTransactionCost(transactionRequest, 0);
Expand All @@ -315,16 +318,17 @@ export default class Provider {
}

/**
* Executes a transaction without actually submitting it to the chain
* If the transaction is missing VariableOuputs
* the transaction will be mutate and VariableOuputs will be added
* Executes a transaction without actually submitting it to the chain.
*
* If the transaction is missing any dependencies,
* the transaction will be mutated and those dependencies will be added.
*/
async call(
transactionRequestLike: TransactionRequestLike,
{ utxoValidation }: ProviderCallParams = {}
): Promise<CallResult> {
const transactionRequest = transactionRequestify(transactionRequestLike);
await this.addMissingVariables(transactionRequest);
await this.estimateTxDependencies(transactionRequest);
const encodedTransaction = hexlify(transactionRequest.toTransactionBytes());
const { dryRun: gqlReceipts } = await this.operations.dryRun({
encodedTransaction,
Expand All @@ -337,13 +341,16 @@ export default class Provider {
}

/**
* Will dryRun a transaction and check for missing VariableOutputs
* Will dryRun a transaction and check for missing dependencies.
*
* If there are missing VariableOutputs
* If there are missing variable outputs,
* `addVariableOutputs` is called on the transaction.
* This process is done at most 10 times
*
* TODO: Investigate support for missing contract IDs
*
* TODO: Add support for missing output messages
*/
async addMissingVariables(transactionRequest: TransactionRequest): Promise<void> {
async estimateTxDependencies(transactionRequest: TransactionRequest): Promise<void> {
let missingOutputVariableCount = 0;
let missingOutputContractIdsCount = 0;
let tries = 0;
Expand Down Expand Up @@ -381,12 +388,13 @@ export default class Provider {
/**
* Executes a signed transaction without applying the states changes
* on the chain.
* If the transaction is missing VariableOuputs
* the transaction will be mutate and VariableOuputs will be added
*
* If the transaction is missing any dependencies,
* the transaction will be mutated and those dependencies will be added
*/
async simulate(transactionRequestLike: TransactionRequestLike): Promise<CallResult> {
const transactionRequest = transactionRequestify(transactionRequestLike);
await this.addMissingVariables(transactionRequest);
await this.estimateTxDependencies(transactionRequest);
const encodedTransaction = hexlify(transactionRequest.toTransactionBytes());
const { dryRun: gqlReceipts } = await this.operations.dryRun({
encodedTransaction,
Expand Down
16 changes: 8 additions & 8 deletions packages/wallet/src/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,8 @@ describe('Account', () => {
.spyOn(providersMod, 'transactionRequestify')
.mockImplementation(() => transactionRequest);

const addMissingVariables = jest
.spyOn(providersMod.Provider.prototype, 'addMissingVariables')
const estimateTxDependencies = jest
.spyOn(providersMod.Provider.prototype, 'estimateTxDependencies')
.mockImplementation(() => Promise.resolve());

const sendTransaction = jest
Expand All @@ -440,8 +440,8 @@ describe('Account', () => {
expect(transactionRequestify.mock.calls.length).toEqual(1);
expect(transactionRequestify.mock.calls[0][0]).toEqual(transactionRequestLike);

expect(addMissingVariables.mock.calls.length).toEqual(1);
expect(addMissingVariables.mock.calls[0][0]).toEqual(transactionRequest);
expect(estimateTxDependencies.mock.calls.length).toEqual(1);
expect(estimateTxDependencies.mock.calls[0][0]).toEqual(transactionRequest);

expect(sendTransaction.mock.calls.length).toEqual(1);
expect(sendTransaction.mock.calls[0][0]).toEqual(transactionRequest);
Expand All @@ -456,8 +456,8 @@ describe('Account', () => {
.spyOn(providersMod, 'transactionRequestify')
.mockImplementation(() => transactionRequest);

const addMissingVariables = jest
.spyOn(providersMod.Provider.prototype, 'addMissingVariables')
const estimateTxDependencies = jest
.spyOn(providersMod.Provider.prototype, 'estimateTxDependencies')
.mockImplementation(() => Promise.resolve());

const simulate = jest
Expand All @@ -475,8 +475,8 @@ describe('Account', () => {
expect(transactionRequestify.mock.calls.length).toBe(1);
expect(transactionRequestify.mock.calls[0][0]).toEqual(transactionRequestLike);

expect(addMissingVariables.mock.calls.length).toBe(1);
expect(addMissingVariables.mock.calls[0][0]).toEqual(transactionRequest);
expect(estimateTxDependencies.mock.calls.length).toBe(1);
expect(estimateTxDependencies.mock.calls[0][0]).toEqual(transactionRequest);

expect(simulate.mock.calls.length).toBe(1);
expect(simulate.mock.calls[0][0]).toEqual(transactionRequest);
Expand Down
4 changes: 2 additions & 2 deletions packages/wallet/src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ export class Account extends AbstractAccount {
transactionRequestLike: TransactionRequestLike
): Promise<TransactionResponse> {
const transactionRequest = transactionRequestify(transactionRequestLike);
await this.provider.addMissingVariables(transactionRequest);
await this.provider.estimateTxDependencies(transactionRequest);
return this.provider.sendTransaction(transactionRequest);
}

Expand All @@ -266,7 +266,7 @@ export class Account extends AbstractAccount {
*/
async simulateTransaction(transactionRequestLike: TransactionRequestLike): Promise<CallResult> {
const transactionRequest = transactionRequestify(transactionRequestLike);
await this.provider.addMissingVariables(transactionRequest);
await this.provider.estimateTxDependencies(transactionRequest);
return this.provider.simulate(transactionRequest);
}
}
4 changes: 2 additions & 2 deletions packages/wallet/src/base-unlocked-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export class BaseWalletUnlocked extends Account {
transactionRequestLike: TransactionRequestLike
): Promise<TransactionResponse> {
const transactionRequest = transactionRequestify(transactionRequestLike);
await this.provider.addMissingVariables(transactionRequest);
await this.provider.estimateTxDependencies(transactionRequest);
return this.provider.sendTransaction(
await this.populateTransactionWitnessesSignature(transactionRequest)
);
Expand All @@ -96,7 +96,7 @@ export class BaseWalletUnlocked extends Account {
*/
async simulateTransaction(transactionRequestLike: TransactionRequestLike): Promise<CallResult> {
const transactionRequest = transactionRequestify(transactionRequestLike);
await this.provider.addMissingVariables(transactionRequest);
await this.provider.estimateTxDependencies(transactionRequest);
return this.provider.call(
await this.populateTransactionWitnessesSignature(transactionRequest),
{
Expand Down
8 changes: 4 additions & 4 deletions packages/wallet/src/wallet-unlocked.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,8 @@ describe('WalletUnlocked', () => {
.spyOn(providersMod, 'transactionRequestify')
.mockImplementation(() => transactionRequest);

const addMissingVariables = jest
.spyOn(providersMod.Provider.prototype, 'addMissingVariables')
const estimateTxDependencies = jest
.spyOn(providersMod.Provider.prototype, 'estimateTxDependencies')
.mockImplementation(() => Promise.resolve());

const call = jest
Expand All @@ -225,8 +225,8 @@ describe('WalletUnlocked', () => {
expect(transactionRequestify.mock.calls.length).toBe(1);
expect(transactionRequestify.mock.calls[0][0]).toEqual(transactionRequestLike);

expect(addMissingVariables.mock.calls.length).toBe(1);
expect(addMissingVariables.mock.calls[0][0]).toEqual(transactionRequest);
expect(estimateTxDependencies.mock.calls.length).toBe(1);
expect(estimateTxDependencies.mock.calls[0][0]).toEqual(transactionRequest);

expect(populateTransactionWitnessesSignatureSpy.mock.calls.length).toBe(1);
expect(populateTransactionWitnessesSignatureSpy.mock.calls[0][0]).toEqual(transactionRequest);
Expand Down

0 comments on commit bf6214c

Please sign in to comment.