Skip to content

Commit

Permalink
Merge branch 'master' into ns/fix/api-docs-deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
nedsalk authored Feb 7, 2025
2 parents 9f08324 + 95255c8 commit cc7abe5
Show file tree
Hide file tree
Showing 15 changed files with 399 additions and 80 deletions.
4 changes: 4 additions & 0 deletions .changeset/angry-pianos-boil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

chore: migrate `pr` + `next` package publishing to GitHub Packages
5 changes: 5 additions & 0 deletions .changeset/curly-brooms-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fuel-ts/account": patch
---

chore: merge gas price and predicate estimation requests
5 changes: 4 additions & 1 deletion .github/actions/ci-setup/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ inputs:
pnpm-version:
description: "PNPM version"
default: 9.4.0
registry-url:
description: "Registry URL"
default: "https://registry.npmjs.org"
runs:
using: "composite"
steps:
Expand All @@ -19,7 +22,7 @@ runs:
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
registry-url: "https://registry.npmjs.org"
registry-url: ${{ inputs.registry-url }}

- name: Setup PNPM
uses: pnpm/action-setup@v4
Expand Down
41 changes: 0 additions & 41 deletions .github/actions/pr-release/action.yaml

This file was deleted.

71 changes: 71 additions & 0 deletions .github/workflows/pr-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Release to @pr-<number> tag on GitHub Packages
on:
pull_request:
workflow_dispatch:

jobs:
release-pr:
name: "Release PR to GitHub Packages"
runs-on: ubuntu-latest
# comment out if:false to enable release PR to GitHub Packages
if: false
permissions: write-all
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.ref }}

- name: CI Setup
uses: ./.github/actions/ci-setup

- name: Create .npmrc
run: |
cat << EOF > "$HOME/.npmrc"
//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN
@FuelLabs:registry=https://npm.pkg.github.com
EOF
env:
HOME: ${{ github.workspace }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Build
run: pnpm build

- name: Release to @pr-${{ github.event.pull_REQUEST.NUMBER }} tag on GitHub Packages
id: release
shell: bash
run: |
pnpm changeset:next
pnpm changeset version --snapshot pr-${{ github.event.pull_REQUEST.NUMBER }}
changetsets=$(pnpm changeset publish --tag pr-${{ github.event.pull_REQUEST.NUMBER }})
published_version=$(echo "$changetsets" | grep -oP '@\K([0-9]+\.){2}[0-9]+-pr-${{ github.event.pull_REQUEST.NUMBER }}-\d+' | head -1)
echo "published_version=$published_version" >> $GITHUB_OUTPUT
env:
NPM_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOME: ${{ github.workspace }}
npm_config_registry: "https://npm.pkg.github.com"

- uses: mshick/add-pr-comment@v2
with:
message: |
This PR is published in GitHub Packages with version **${{ steps.release.outputs.published_version }}**
Install using the following command:
```bash
pnpm add @fuellabs/fuels@${{ steps.release.outputs.published_version }}
```
Or update your package.json:
```json
"dependencies": {
"@fuellabs/fuels": "${{ steps.release.outputs.published_version }}"
}
```
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
19 changes: 16 additions & 3 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,18 @@ jobs:
LATEST_RELEASE: ${{ env.LATEST_RELEASE }}
RELEASE_VERSION_HIGHER_THAN_LATEST: ${{ env.RELEASE_VERSION_HIGHER_THAN_LATEST }}

- name: Release to @next tag on npm
- name: Create .npmrc
if: github.ref_name == 'master' && steps.changesets.outputs.published != 'true'
run: |
cat << EOF > "$HOME/.npmrc"
//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN
@FuelLabs:registry=https://npm.pkg.github.com
EOF
env:
HOME: ${{ github.workspace }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Release to @next tag on GitHub Packages
if: github.ref_name == 'master' && steps.changesets.outputs.published != 'true'
run: |
git checkout master
Expand All @@ -105,12 +116,14 @@ jobs:
fi
pnpm changeset:next
git add .changeset/fuel-labs-ci.md
pnpm changeset version --snapshot next
pnpm changeset publish --tag next
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_DEPLOY_TOKEN }}
NPM_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOME: ${{ github.workspace }}
npm_config_registry: "https://npm.pkg.github.com"

# ensure docs API is always deployed after merge of changeset PR
- name: Get the last commit message and set env vars
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"prettier:format": "prettier --write packages --write apps/docs",
"verify:package-exports": "tsx ./scripts/verify-package-exports",
"changeset:publish": "tsx ./scripts/changeset/changeset-publish",
"changeset:next": "tsx ./scripts/changeset/changeset-next",
"changeset:next": "tsx ./scripts/changeset/changeset-next.mts",
"changeset:version-with-docs": "tsx ./scripts/changeset/changeset-version-with-docs",
"changeset:update-changelog": "tsx ./scripts/changeset/update-changelog.mts",
"changeset:get-latest-release": "tsx ./scripts/changeset/get-latest-release.mts",
Expand Down
12 changes: 12 additions & 0 deletions packages/account/src/providers/operations.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,18 @@ query estimatePredicates($encodedTransaction: HexString!) {
}
}

query estimatePredicatesAndGasPrice(
$encodedTransaction: HexString!
$blockHorizon: U32!
) {
estimatePredicates(tx: $encodedTransaction) {
...transactionEstimatePredicatesFragment
}
estimateGasPrice(blockHorizon: $blockHorizon) {
gasPrice
}
}

query getLatestBlock {
chain {
latestBlock {
Expand Down
114 changes: 86 additions & 28 deletions packages/account/src/providers/provider.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type { AddressInput } from '@fuel-ts/address';
import { Address } from '@fuel-ts/address';
import { ErrorCode, FuelError } from '@fuel-ts/errors';
import { BN, bn } from '@fuel-ts/math';
import type { BN } from '@fuel-ts/math';
import { bn } from '@fuel-ts/math';
import type { Transaction } from '@fuel-ts/transactions';
import { InputType, InputMessageCoder, TransactionCoder } from '@fuel-ts/transactions';
import type { BytesLike } from '@fuel-ts/utils';
import { arrayify, hexlify, DateTime, isDefined } from '@fuel-ts/utils';
import { checkFuelCoreVersionCompatibility, versions } from '@fuel-ts/versions';
import { equalBytes } from '@noble/curves/abstract/utils';
import type { DocumentNode } from 'graphql';
import { GraphQLClient } from 'graphql-request';
import type { GraphQLClientResponse, GraphQLResponse } from 'graphql-request/src/types';
Expand All @@ -30,6 +30,7 @@ import type {
GqlRelayedTransactionFailed,
Requester,
GqlBlockFragment,
GqlEstimatePredicatesQuery,
} from './__generated__/operations';
import type { Coin } from './coin';
import type { CoinQuantity, CoinQuantityLike } from './coin-quantity';
Expand All @@ -47,6 +48,7 @@ import type {
ScriptTransactionRequest,
} from './transaction-request';
import {
isPredicate,
isTransactionTypeCreate,
isTransactionTypeScript,
transactionRequestify,
Expand Down Expand Up @@ -947,48 +949,78 @@ export default class Provider {
}

/**
* Verifies whether enough gas is available to complete transaction.
* Estimates the gas usage for predicates in a transaction request.
*
* @template T - The type of the transaction request object.
*
* @param transactionRequest - The transaction request object.
* @returns A promise that resolves to the estimated transaction request object.
* @param transactionRequest - The transaction request to estimate predicates for.
* @returns A promise that resolves to the updated transaction request with estimated gas usage for predicates.
*/
async estimatePredicates<T extends TransactionRequest>(transactionRequest: T): Promise<T> {
const shouldEstimatePredicates = Boolean(
transactionRequest.inputs.find(
(input) =>
'predicate' in input &&
input.predicate &&
!equalBytes(arrayify(input.predicate), arrayify('0x')) &&
new BN(input.predicateGasUsed).isZero()
)
const shouldEstimatePredicates = transactionRequest.inputs.some(
(input) => isPredicate(input) && bn(input.predicateGasUsed).isZero()
);

if (!shouldEstimatePredicates) {
return transactionRequest;
}

const encodedTransaction = hexlify(transactionRequest.toTransactionBytes());

const response = await this.operations.estimatePredicates({
encodedTransaction,
});

const {
estimatePredicates: { inputs },
} = response;
const { estimatePredicates } = response;

if (inputs) {
inputs.forEach((input, index) => {
if ('predicateGasUsed' in input && bn(input.predicateGasUsed).gt(0)) {
// eslint-disable-next-line no-param-reassign
(<CoinTransactionRequestInput>transactionRequest.inputs[index]).predicateGasUsed =
input.predicateGasUsed;
}
});
}
// eslint-disable-next-line no-param-reassign
transactionRequest = this.parseEstimatePredicatesResponse(
transactionRequest,
estimatePredicates
);

return transactionRequest;
}

/**
* Estimates the gas price and predicates for a given transaction request and block horizon.
*
* @param transactionRequest - The transaction request to estimate predicates and gas price for.
* @param blockHorizon - The block horizon to use for gas price estimation.
* @returns A promise that resolves to an object containing the updated transaction
* request and the estimated gas price.
*/
async estimatePredicatesAndGasPrice<T extends TransactionRequest>(
transactionRequest: T,
blockHorizon: number
) {
const shouldEstimatePredicates = transactionRequest.inputs.some(
(input) => isPredicate(input) && bn(input.predicateGasUsed).isZero()
);

if (!shouldEstimatePredicates) {
const gasPrice = await this.estimateGasPrice(blockHorizon);

return { transactionRequest, gasPrice };
}

const {
estimateGasPrice: { gasPrice },
estimatePredicates,
} = await this.operations.estimatePredicatesAndGasPrice({
blockHorizon: String(blockHorizon),
encodedTransaction: hexlify(transactionRequest.toTransactionBytes()),
});

// eslint-disable-next-line no-param-reassign
transactionRequest = this.parseEstimatePredicatesResponse(
transactionRequest,
estimatePredicates
);

return { transactionRequest, gasPrice: bn(gasPrice) };
}

/**
* Will dryRun a transaction and check for missing dependencies.
*
Expand Down Expand Up @@ -1355,10 +1387,16 @@ export default class Provider {
addedSignatures = signedRequest.witnesses.length - lengthBefore;
}

await this.estimatePredicates(signedRequest);
txRequestClone.updatePredicateGasUsed(signedRequest.inputs);
let gasPrice: BN;

const gasPrice = gasPriceParam ?? (await this.estimateGasPrice(10));
if (gasPriceParam) {
gasPrice = gasPriceParam;
await this.estimatePredicates(signedRequest);
} else {
({ gasPrice } = await this.estimatePredicatesAndGasPrice(signedRequest, 10));
}

txRequestClone.updatePredicateGasUsed(signedRequest.inputs);

/**
* Calculate minGas and maxGas based on the real transaction
Expand Down Expand Up @@ -2176,4 +2214,24 @@ export default class Provider {
statusReason: status.reason,
});
}

/**
* @hidden
*/
private parseEstimatePredicatesResponse<T extends TransactionRequest>(
transactionRequest: T,
{ inputs }: GqlEstimatePredicatesQuery['estimatePredicates']
): T {
if (inputs) {
inputs.forEach((input, i) => {
if (input && 'predicateGasUsed' in input && bn(input.predicateGasUsed).gt(0)) {
// eslint-disable-next-line no-param-reassign
(<CoinTransactionRequestInput>transactionRequest.inputs[i]).predicateGasUsed =
input.predicateGasUsed;
}
});
}

return transactionRequest;
}
}
Loading

0 comments on commit cc7abe5

Please sign in to comment.