diff --git a/.changeset/cool-deers-fetch.md b/.changeset/cool-deers-fetch.md new file mode 100644 index 0000000000..7c7b889db2 --- /dev/null +++ b/.changeset/cool-deers-fetch.md @@ -0,0 +1,11 @@ +--- +"@fuel-ts/transactions": minor +"@fuel-ts/fuel-core": minor +"@fuel-ts/versions": minor +"@fuel-ts/account": minor +"@fuel-ts/program": minor +"@fuel-ts/script": minor +"@fuel-ts/utils": minor +--- + +chore!: upgrade `fuel-core` to `0.26.0` diff --git a/.fuel-core/configs/chainConfig.json b/.fuel-core/configs/chainConfig.json index aebccd7fde..81083c0945 100644 --- a/.fuel-core/configs/chainConfig.json +++ b/.fuel-core/configs/chainConfig.json @@ -8,7 +8,8 @@ "max_outputs": 255, "max_witnesses": 255, "max_gas_per_tx": 30000000, - "max_size": 112640 + "max_size": 112640, + "max_bytecode_subsections": 256 } }, "predicate_params": { diff --git a/.fuel-core/configs/state_transition_bytecode.wasm b/.fuel-core/configs/state_transition_bytecode.wasm new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/demo-nextjs/package.json b/apps/demo-nextjs/package.json index 5e2a4faa35..ec72f435ac 100644 --- a/apps/demo-nextjs/package.json +++ b/apps/demo-nextjs/package.json @@ -10,7 +10,7 @@ "pretest": "pnpm original:build" }, "dependencies": { - "@fuels/vm-asm": "0.42.1", + "@fuels/vm-asm": "0.49.0", "@types/node": "18.15.3", "@types/react-dom": "18.2.4", "@types/react": "18.2.9", diff --git a/apps/demo-react-cra/package.json b/apps/demo-react-cra/package.json index 790e038849..43155cef68 100644 --- a/apps/demo-react-cra/package.json +++ b/apps/demo-react-cra/package.json @@ -3,7 +3,7 @@ "version": "0.1.29", "private": true, "dependencies": { - "@fuels/vm-asm": "0.42.1", + "@fuels/vm-asm": "0.49.0", "@testing-library/react": "^13.4.0", "@types/node": "^16.18.34", "@types/react": "^18.2.9", diff --git a/apps/demo-react-vite/package.json b/apps/demo-react-vite/package.json index 1e5bb410f7..f4a5a897fe 100644 --- a/apps/demo-react-vite/package.json +++ b/apps/demo-react-vite/package.json @@ -11,7 +11,7 @@ "pretest": "pnpm original:build" }, "dependencies": { - "@fuels/vm-asm": "0.42.1", + "@fuels/vm-asm": "0.49.0", "fuels": "workspace:*", "react-dom": "^18.2.0", "react": "^18.2.0" diff --git a/packages/account/codegen.json b/packages/account/codegen.json index 68a738ed66..0ba1deb7f5 100644 --- a/packages/account/codegen.json +++ b/packages/account/codegen.json @@ -11,19 +11,23 @@ ], "config": { "scalars": { - "DateTime": "string", - "HexString": "string", - "Bytes32": "string", - "UtxoId": "string", - "U64": "string", "Address": "string", - "BlockId": "string", - "TransactionId": "string", "AssetId": "string", + "BlockId": "string", + "Bytes32": "string", "ContractId": "string", - "Salt": "string", + "HexString": "string", "Nonce": "string", - "Tai64Timestamp": "string" + "RelayedTransactionId": "string", + "Salt": "string", + "Signature": "string", + "Tai64Timestamp": "string", + "TransactionId": "string", + "TxPointer": "string", + "U16": "string", + "U32": "string", + "U64": "string", + "UtxoId": "string" }, "useTypeImports": true, "nonOptionalTypename": true, diff --git a/packages/account/package.json b/packages/account/package.json index 07aa8d1302..cb7cdbe435 100644 --- a/packages/account/package.json +++ b/packages/account/package.json @@ -59,7 +59,7 @@ "@fuel-ts/transactions": "workspace:*", "@fuel-ts/utils": "workspace:*", "@fuel-ts/versions": "workspace:*", - "@fuels/vm-asm": "0.42.1", + "@fuels/vm-asm": "0.49.0", "@noble/curves": "^1.3.0", "ethers": "^6.7.1", "events": "^3.3.0", diff --git a/packages/account/src/predicate/predicate.ts b/packages/account/src/predicate/predicate.ts index 6e3d4ecbc3..0ac446cdc0 100644 --- a/packages/account/src/predicate/predicate.ts +++ b/packages/account/src/predicate/predicate.ts @@ -128,7 +128,7 @@ export class Predicate extends Account { const paddedCode = new ByteArrayCoder(this.bytes.length).encode(this.bytes); const VM_TX_MEMORY = calculateVmTxMemory({ - maxInputs: this.provider.getChain().consensusParameters.maxInputs.toNumber(), + maxInputs: this.provider.getChain().consensusParameters.txParameters.maxInputs.toNumber(), }); const OFFSET = VM_TX_MEMORY + diff --git a/packages/account/src/providers/fuel-core-schema.graphql b/packages/account/src/providers/fuel-core-schema.graphql index 57a318cb7f..fa6bf8518e 100644 --- a/packages/account/src/providers/fuel-core-schema.graphql +++ b/packages/account/src/providers/fuel-core-schema.graphql @@ -201,6 +201,11 @@ type ConsensusParameters { privilegedAddress: Address! } +type ConsensusParametersPurpose { + witnessIndex: U16! + checksum: Bytes32! +} + enum ConsensusParametersVersion { V1 } @@ -285,11 +290,15 @@ type DryRunFailureStatus { programState: ProgramState reason: String! receipts: [Receipt!]! + totalGas: U64! + totalFee: U64! } type DryRunSuccessStatus { programState: ProgramState receipts: [Receipt!]! + totalGas: U64! + totalFee: U64! } type DryRunTransactionExecutionStatus { @@ -323,6 +332,8 @@ type FailureStatus { reason: String! programState: ProgramState receipts: [Receipt!]! + totalGas: U64! + totalFee: U64! } type FeeParameters { @@ -474,6 +485,11 @@ type Genesis { The Binary Merkle Tree root of all genesis messages. """ messagesRoot: Bytes32! + + """ + The Binary Merkle Tree root of all processed transaction ids. + """ + transactionsRoot: Bytes32! } type Header { @@ -500,12 +516,12 @@ type Header { """ Number of transactions in this block. """ - transactionsCount: U64! + transactionsCount: U16! """ Number of message receipts in this block. """ - messageReceiptCount: U64! + messageReceiptCount: U32! """ Merkle root of transactions. @@ -1023,7 +1039,12 @@ type Query { commitBlockHeight: U32 ): MessageProof messageStatus(nonce: Nonce!): MessageStatus! - message(nonce: Nonce!): Message + relayedTransactionStatus( + """ + The id of the relayed tx + """ + id: RelayedTransactionId! + ): RelayedTransactionStatus } type Receipt { @@ -1077,6 +1098,15 @@ enum ReceiptType { BURN } +type RelayedTransactionFailed { + blockHeight: U32! + failure: String! +} + +scalar RelayedTransactionId + +union RelayedTransactionStatus = RelayedTransactionFailed + enum ReturnType { RETURN RETURN_DATA @@ -1136,6 +1166,10 @@ type SqueezedOutStatus { reason: String! } +type StateTransitionPurpose { + root: Bytes32! +} + type SubmittedStatus { time: Tai64Timestamp! } @@ -1174,6 +1208,8 @@ type SuccessStatus { time: Tai64Timestamp! programState: ProgramState receipts: [Receipt!]! + totalGas: U64! + totalFee: U64! } scalar Tai64Timestamp @@ -1193,6 +1229,8 @@ type Transaction { isScript: Boolean! isCreate: Boolean! isMint: Boolean! + isUpgrade: Boolean! + isUpload: Boolean! inputs: [Input!] outputs: [Output!]! outputContract: ContractOutput @@ -1204,6 +1242,11 @@ type Transaction { bytecodeWitnessIndex: U16 salt: Salt storageSlots: [HexString!] + bytecodeRoot: Bytes32 + subsectionIndex: U16 + subsectionsNumber: U16 + proofSet: [Bytes32!] + upgradePurpose: UpgradePurpose """ Return the transaction bytes using canonical encoding @@ -1258,6 +1301,7 @@ type TxParameters { maxWitnesses: U32! maxGasPerTx: U64! maxSize: U64! + maxBytecodeSubsections: U16! } enum TxParametersVersion { @@ -1272,6 +1316,8 @@ scalar U32 scalar U64 +union UpgradePurpose = ConsensusParametersPurpose | StateTransitionPurpose + scalar UtxoId type VariableOutput { diff --git a/packages/account/src/providers/message.ts b/packages/account/src/providers/message.ts index c4429ba174..dcafe0abc0 100644 --- a/packages/account/src/providers/message.ts +++ b/packages/account/src/providers/message.ts @@ -38,7 +38,7 @@ export type MerkleProof = { export type BlockHeader = { id: string; daHeight: BN; - transactionsCount: BN; + transactionsCount: number; transactionsRoot: string; height: BN; prevRoot: string; @@ -48,7 +48,7 @@ export type BlockHeader = { eventInboxRoot: string; consensusParametersVersion: number; stateTransitionBytecodeVersion: number; - messageReceiptCount: BN; + messageReceiptCount: number; }; /** diff --git a/packages/account/src/providers/operations.graphql b/packages/account/src/providers/operations.graphql index 939afe7338..b707573058 100644 --- a/packages/account/src/providers/operations.graphql +++ b/packages/account/src/providers/operations.graphql @@ -15,9 +15,6 @@ fragment transactionStatusFragment on TransactionStatus { id } time - receipts { - ...receiptFragment - } programState { returnType data @@ -25,11 +22,15 @@ fragment transactionStatusFragment on TransactionStatus { receipts { ...receiptFragment } + totalGas + totalFee } ... on FailureStatus { block { id } + totalGas + totalFee time reason receipts { @@ -72,6 +73,8 @@ fragment transactionEstimatePredicatesFragment on Transaction { } fragment dryRunFailureStatusFragment on DryRunFailureStatus { + totalGas + totalFee reason programState { returnType @@ -80,6 +83,8 @@ fragment dryRunFailureStatusFragment on DryRunFailureStatus { } fragment dryRunSuccessStatusFragment on DryRunSuccessStatus { + totalGas + totalFee programState { returnType data @@ -235,6 +240,7 @@ fragment TxParametersFragment on TxParameters { maxWitnesses maxGasPerTx maxSize + maxBytecodeSubsections } fragment PredicateParametersFragment on PredicateParameters { @@ -494,6 +500,13 @@ fragment nodeInfoFragment on NodeInfo { nodeVersion } +fragment relayedTransactionStatusFragment on RelayedTransactionStatus { + ... on RelayedTransactionFailed { + blockHeight + failure + } +} + query getNodeInfo { nodeInfo { ...nodeInfoFragment @@ -729,6 +742,14 @@ query getMessageStatus($nonce: Nonce!) { } } +query getRelayedTransactionStatus( + $relayedTransactionId: RelayedTransactionId! +) { + relayedTransactionStatus(id: $relayedTransactionId) { + ...relayedTransactionStatusFragment + } +} + mutation dryRun($encodedTransactions: [HexString!]!, $utxoValidation: Boolean) { dryRun(txs: $encodedTransactions, utxoValidation: $utxoValidation) { ...dryRunTransactionExecutionStatusFragment diff --git a/packages/account/src/providers/provider.test.ts b/packages/account/src/providers/provider.test.ts index 6779742a7a..32d7064d25 100644 --- a/packages/account/src/providers/provider.test.ts +++ b/packages/account/src/providers/provider.test.ts @@ -62,7 +62,7 @@ describe('Provider', () => { const version = await provider.getVersion(); - expect(version).toEqual('0.24.3'); + expect(version).toEqual('0.26.0'); }); it('can call()', async () => { @@ -187,21 +187,35 @@ describe('Provider', () => { const provider = await Provider.create(FUEL_NETWORK_URL); const { consensusParameters } = provider.getChain(); + expect(consensusParameters.version).toBeDefined(); + expect(consensusParameters.chainId).toBeDefined(); expect(consensusParameters.baseAssetId).toBeDefined(); - expect(consensusParameters.contractMaxSize).toBeDefined(); - expect(consensusParameters.maxInputs).toBeDefined(); - expect(consensusParameters.maxOutputs).toBeDefined(); - expect(consensusParameters.maxWitnesses).toBeDefined(); - expect(consensusParameters.maxGasPerTx).toBeDefined(); - expect(consensusParameters.maxScriptLength).toBeDefined(); - expect(consensusParameters.maxScriptDataLength).toBeDefined(); - expect(consensusParameters.maxStorageSlots).toBeDefined(); - expect(consensusParameters.maxPredicateLength).toBeDefined(); - expect(consensusParameters.maxPredicateDataLength).toBeDefined(); - expect(consensusParameters.maxGasPerPredicate).toBeDefined(); - expect(consensusParameters.gasPriceFactor).toBeDefined(); - expect(consensusParameters.gasPerByte).toBeDefined(); - expect(consensusParameters.maxMessageDataLength).toBeDefined(); + + expect(consensusParameters.feeParameters.version).toBeDefined(); + expect(consensusParameters.feeParameters.gasPriceFactor).toBeDefined(); + expect(consensusParameters.feeParameters.gasPerByte).toBeDefined(); + + expect(consensusParameters.txParameters.version).toBeDefined(); + expect(consensusParameters.txParameters.maxSize).toBeDefined(); + expect(consensusParameters.txParameters.maxInputs).toBeDefined(); + expect(consensusParameters.txParameters.maxOutputs).toBeDefined(); + expect(consensusParameters.txParameters.maxWitnesses).toBeDefined(); + expect(consensusParameters.txParameters.maxGasPerTx).toBeDefined(); + expect(consensusParameters.txParameters.maxBytecodeSubsections).toBeDefined(); + + expect(consensusParameters.scriptParameters.version).toBeDefined(); + expect(consensusParameters.scriptParameters.maxScriptLength).toBeDefined(); + expect(consensusParameters.scriptParameters.maxScriptDataLength).toBeDefined(); + + expect(consensusParameters.contractParameters.version).toBeDefined(); + expect(consensusParameters.contractParameters.contractMaxSize).toBeDefined(); + expect(consensusParameters.contractParameters.maxStorageSlots).toBeDefined(); + + expect(consensusParameters.predicateParameters.version).toBeDefined(); + expect(consensusParameters.predicateParameters.maxPredicateLength).toBeDefined(); + expect(consensusParameters.predicateParameters.maxPredicateDataLength).toBeDefined(); + expect(consensusParameters.predicateParameters.maxGasPerPredicate).toBeDefined(); + expect(consensusParameters.predicateParameters.maxMessageDataLength).toBeDefined(); }); it('gets the chain ID', async () => { diff --git a/packages/account/src/providers/provider.ts b/packages/account/src/providers/provider.ts index 3bc3af888c..2e875ef835 100644 --- a/packages/account/src/providers/provider.ts +++ b/packages/account/src/providers/provider.ts @@ -22,11 +22,18 @@ import type { Predicate } from '../predicate'; import { getSdk as getOperationsSdk } from './__generated__/operations'; import type { GqlChainInfoFragmentFragment, + GqlConsensusParametersVersion, + GqlContractParameters, GqlDryRunFailureStatusFragmentFragment, GqlDryRunSuccessStatusFragmentFragment, + GqlFeeParameters, GqlGasCosts, GqlGetBlocksQueryVariables, GqlMessage, + GqlPredicateParameters, + GqlRelayedTransactionFailed, + GqlScriptParameters, + GqlTxParameters, } from './__generated__/operations'; import type { Coin } from './coin'; import type { CoinQuantity, CoinQuantityLike } from './coin-quantity'; @@ -60,7 +67,7 @@ export type DryRunStatus = export type CallResult = { receipts: TransactionResultReceipt[]; - dryrunStatus?: DryRunStatus; + dryRunStatus?: DryRunStatus; }; export type EstimateTxDependenciesReturns = CallResult & { @@ -86,24 +93,27 @@ export type ContractResult = { bytecode: string; }; -type ConsensusParameters = { - contractMaxSize: BN; - maxInputs: BN; - maxOutputs: BN; - maxWitnesses: BN; - maxGasPerTx: BN; - maxScriptLength: BN; - maxScriptDataLength: BN; - maxStorageSlots: BN; - maxPredicateLength: BN; - maxPredicateDataLength: BN; - maxGasPerPredicate: BN; - gasPriceFactor: BN; - gasPerByte: BN; - maxMessageDataLength: BN; +type ModifyStringToBN = { + [P in keyof T]: P extends 'version' ? T[P] : T[P] extends string ? BN : T[P]; +}; + +export type FeeParameters = Omit; +export type ContractParameters = Omit; +export type PredicateParameters = Omit; +export type ScriptParameters = Omit; +export type TxParameters = Omit; +export type GasCosts = Omit; + +export type ConsensusParameters = { + version: GqlConsensusParametersVersion; chainId: BN; - gasCosts: GqlGasCosts; baseAssetId: string; + feeParameters: ModifyStringToBN; + contractParameters: ModifyStringToBN; + predicateParameters: ModifyStringToBN; + scriptParameters: ModifyStringToBN; + txParameters: ModifyStringToBN; + gasCosts: GasCosts; }; /** @@ -113,7 +123,6 @@ export type ChainInfo = { name: string; baseChainHeight: BN; consensusParameters: ConsensusParameters; - gasCosts: GqlGasCosts; latestBlock: { id: string; height: BN; @@ -154,38 +163,65 @@ export type TransactionCost = { estimatedPredicates: TransactionRequestInput[]; requiredQuantities: CoinQuantity[]; addedSignatures: number; + dryRunStatus?: DryRunStatus; }; // #endregion cost-estimation-1 const processGqlChain = (chain: GqlChainInfoFragmentFragment): ChainInfo => { const { name, daHeight, consensusParameters, latestBlock } = chain; - const { contractParams, feeParams, predicateParams, scriptParams, txParams, gasCosts } = - consensusParameters; + const { + contractParams, + feeParams, + predicateParams, + scriptParams, + txParams, + gasCosts, + baseAssetId, + chainId, + version, + } = consensusParameters; return { name, baseChainHeight: bn(daHeight), consensusParameters: { - contractMaxSize: bn(contractParams.contractMaxSize), - maxInputs: bn(txParams.maxInputs), - maxOutputs: bn(txParams.maxOutputs), - maxWitnesses: bn(txParams.maxWitnesses), - maxGasPerTx: bn(txParams.maxGasPerTx), - maxScriptLength: bn(scriptParams.maxScriptLength), - maxScriptDataLength: bn(scriptParams.maxScriptDataLength), - maxStorageSlots: bn(contractParams.maxStorageSlots), - maxPredicateLength: bn(predicateParams.maxPredicateLength), - maxPredicateDataLength: bn(predicateParams.maxPredicateDataLength), - maxGasPerPredicate: bn(predicateParams.maxGasPerPredicate), - gasPriceFactor: bn(feeParams.gasPriceFactor), - gasPerByte: bn(feeParams.gasPerByte), - maxMessageDataLength: bn(predicateParams.maxMessageDataLength), - chainId: bn(consensusParameters.chainId), - baseAssetId: consensusParameters.baseAssetId, + version, + chainId: bn(chainId), + baseAssetId, + feeParameters: { + version: feeParams.version, + gasPerByte: bn(feeParams.gasPerByte), + gasPriceFactor: bn(feeParams.gasPriceFactor), + }, + contractParameters: { + version: contractParams.version, + contractMaxSize: bn(contractParams.contractMaxSize), + maxStorageSlots: bn(contractParams.maxStorageSlots), + }, + txParameters: { + version: txParams.version, + maxInputs: bn(txParams.maxInputs), + maxOutputs: bn(txParams.maxOutputs), + maxWitnesses: bn(txParams.maxWitnesses), + maxGasPerTx: bn(txParams.maxGasPerTx), + maxSize: bn(txParams.maxSize), + maxBytecodeSubsections: bn(txParams.maxBytecodeSubsections), + }, + predicateParameters: { + version: predicateParams.version, + maxPredicateLength: bn(predicateParams.maxPredicateLength), + maxPredicateDataLength: bn(predicateParams.maxPredicateDataLength), + maxGasPerPredicate: bn(predicateParams.maxGasPerPredicate), + maxMessageDataLength: bn(predicateParams.maxMessageDataLength), + }, + scriptParameters: { + version: scriptParams.version, + maxScriptLength: bn(scriptParams.maxScriptLength), + maxScriptDataLength: bn(scriptParams.maxScriptDataLength), + }, gasCosts, }, - gasCosts, latestBlock: { id: latestBlock.id, height: bn(latestBlock.height), @@ -398,8 +434,12 @@ export default class Provider { * Returns some helpful parameters related to gas fees. */ getGasConfig() { - const { maxGasPerTx, maxGasPerPredicate, gasPriceFactor, gasPerByte, gasCosts } = - this.getChain().consensusParameters; + const { + txParameters: { maxGasPerTx }, + predicateParameters: { maxGasPerPredicate }, + feeParameters: { gasPriceFactor, gasPerByte }, + gasCosts, + } = this.getChain().consensusParameters; return { maxGasPerTx, maxGasPerPredicate, @@ -667,10 +707,10 @@ export default class Provider { encodedTransactions: encodedTransaction, utxoValidation: utxoValidation || false, }); - const [{ receipts: rawReceipts, status }] = dryRunStatuses; + const [{ receipts: rawReceipts, status: dryRunStatus }] = dryRunStatuses; const receipts = rawReceipts.map(processGqlReceipt); - return { receipts, dryrunStatus: status }; + return { receipts, dryRunStatus }; } /** @@ -738,7 +778,7 @@ export default class Provider { let receipts: TransactionResultReceipt[] = []; const missingContractIds: string[] = []; let outputVariables = 0; - let dryrunStatus: DryRunStatus | undefined; + let dryRunStatus: DryRunStatus | undefined; for (let attempt = 0; attempt < MAX_RETRIES; attempt++) { const { @@ -749,7 +789,7 @@ export default class Provider { }); receipts = rawReceipts.map(processGqlReceipt); - dryrunStatus = status; + dryRunStatus = status; const { missingOutputVariables, missingOutputContractIds } = getReceiptsWithMissingData(receipts); @@ -780,7 +820,7 @@ export default class Provider { receipts, outputVariables, missingContractIds, - dryrunStatus, + dryRunStatus, }; } @@ -801,7 +841,7 @@ export default class Provider { receipts: [], outputVariables: 0, missingContractIds: [], - dryrunStatus: undefined, + dryRunStatus: undefined, })); const allRequests = clone(transactionRequests); @@ -836,7 +876,7 @@ export default class Provider { const { receipts: rawReceipts, status } = dryRunResults.dryRun[i]; const result = results[requestIdx]; result.receipts = rawReceipts.map(processGqlReceipt); - result.dryrunStatus = status; + result.dryRunStatus = status; const { missingOutputVariables, missingOutputContractIds } = getReceiptsWithMissingData( result.receipts ); @@ -882,7 +922,7 @@ export default class Provider { const results = dryRunStatuses.map(({ receipts: rawReceipts, status }) => { const receipts = rawReceipts.map(processGqlReceipt); - return { receipts, dryrunStatus: status }; + return { receipts, dryRunStatus: status }; }); return results; @@ -1064,6 +1104,7 @@ export default class Provider { }); let receipts: TransactionResultReceipt[] = []; + let dryRunStatus: DryRunStatus | undefined; let missingContractIds: string[] = []; let outputVariables = 0; let gasUsed = bn(0); @@ -1077,10 +1118,9 @@ export default class Provider { await signatureCallback(txRequestClone); } - const result = await this.estimateTxDependencies(txRequestClone); - receipts = result.receipts; - outputVariables = result.outputVariables; - missingContractIds = result.missingContractIds; + ({ receipts, missingContractIds, outputVariables, dryRunStatus } = + await this.estimateTxDependencies(txRequestClone)); + gasUsed = isScriptTransaction ? getGasUsedFromReceipts(receipts) : gasUsed; txRequestClone.gasLimit = gasUsed; @@ -1104,6 +1144,7 @@ export default class Provider { missingContractIds, addedSignatures, estimatedPredicates: txRequestClone.inputs, + dryRunStatus, }; } @@ -1551,32 +1592,32 @@ export default class Provider { messageBlockHeader: { id: messageBlockHeader.id, daHeight: bn(messageBlockHeader.daHeight), - transactionsCount: bn(messageBlockHeader.transactionsCount), + transactionsCount: Number(messageBlockHeader.transactionsCount), transactionsRoot: messageBlockHeader.transactionsRoot, height: bn(messageBlockHeader.height), prevRoot: messageBlockHeader.prevRoot, time: messageBlockHeader.time, applicationHash: messageBlockHeader.applicationHash, - messageReceiptCount: bn(messageBlockHeader.messageReceiptCount), + messageReceiptCount: Number(messageBlockHeader.messageReceiptCount), messageOutboxRoot: messageBlockHeader.messageOutboxRoot, - consensusParametersVersion: messageBlockHeader.consensusParametersVersion, + consensusParametersVersion: Number(messageBlockHeader.consensusParametersVersion), eventInboxRoot: messageBlockHeader.eventInboxRoot, - stateTransitionBytecodeVersion: messageBlockHeader.stateTransitionBytecodeVersion, + stateTransitionBytecodeVersion: Number(messageBlockHeader.stateTransitionBytecodeVersion), }, commitBlockHeader: { id: commitBlockHeader.id, daHeight: bn(commitBlockHeader.daHeight), - transactionsCount: bn(commitBlockHeader.transactionsCount), + transactionsCount: Number(commitBlockHeader.transactionsCount), transactionsRoot: commitBlockHeader.transactionsRoot, height: bn(commitBlockHeader.height), prevRoot: commitBlockHeader.prevRoot, time: commitBlockHeader.time, applicationHash: commitBlockHeader.applicationHash, - messageReceiptCount: bn(commitBlockHeader.messageReceiptCount), + messageReceiptCount: Number(commitBlockHeader.messageReceiptCount), messageOutboxRoot: commitBlockHeader.messageOutboxRoot, - consensusParametersVersion: commitBlockHeader.consensusParametersVersion, + consensusParametersVersion: Number(commitBlockHeader.consensusParametersVersion), eventInboxRoot: commitBlockHeader.eventInboxRoot, - stateTransitionBytecodeVersion: commitBlockHeader.stateTransitionBytecodeVersion, + stateTransitionBytecodeVersion: Number(commitBlockHeader.stateTransitionBytecodeVersion), }, sender: Address.fromAddressOrString(sender), recipient: Address.fromAddressOrString(recipient), @@ -1647,4 +1688,18 @@ export default class Provider { return message; } + + async getRelayedTransactionStatus( + relayedTransactionId: string + ): Promise { + const { relayedTransactionStatus } = await this.operations.getRelayedTransactionStatus({ + relayedTransactionId, + }); + + if (!relayedTransactionStatus) { + return null; + } + + return relayedTransactionStatus; + } } diff --git a/packages/account/src/providers/transaction-request/script-transaction-request.ts b/packages/account/src/providers/transaction-request/script-transaction-request.ts index 3c7d33d05a..c213eaada2 100644 --- a/packages/account/src/providers/transaction-request/script-transaction-request.ts +++ b/packages/account/src/providers/transaction-request/script-transaction-request.ts @@ -9,8 +9,7 @@ import type { TransactionScript } from '@fuel-ts/transactions'; import { InputType, OutputType, TransactionType } from '@fuel-ts/transactions'; import { arrayify, hexlify } from '@fuel-ts/utils'; -import type { GqlGasCosts } from '../__generated__/operations'; -import type { ChainInfo } from '../provider'; +import type { ChainInfo, GasCosts } from '../provider'; import { calculateMetadataGasForTxScript, getMaxGas } from '../utils/gas'; import { hashTransaction } from './hash-transaction'; @@ -155,7 +154,10 @@ export class ScriptTransactionRequest extends BaseTransactionRequest { calculateMaxGas(chainInfo: ChainInfo, minGas: BN): BN { const { consensusParameters } = chainInfo; - const { gasPerByte, maxGasPerTx } = consensusParameters; + const { + feeParameters: { gasPerByte }, + txParameters: { maxGasPerTx }, + } = consensusParameters; const witnessesLength = this.toTransaction().witnesses.reduce( (acc, wit) => acc + wit.dataLength, @@ -224,7 +226,7 @@ export class ScriptTransactionRequest extends BaseTransactionRequest { return this; } - metadataGas(gasCosts: GqlGasCosts): BN { + metadataGas(gasCosts: GasCosts): BN { return calculateMetadataGasForTxScript({ gasCosts, txBytesSize: this.byteSize(), diff --git a/packages/account/src/providers/transaction-request/transaction-request.ts b/packages/account/src/providers/transaction-request/transaction-request.ts index eb22884618..b421d6a8d5 100644 --- a/packages/account/src/providers/transaction-request/transaction-request.ts +++ b/packages/account/src/providers/transaction-request/transaction-request.ts @@ -16,12 +16,11 @@ import { import { concat, hexlify, isDefined } from '@fuel-ts/utils'; import type { Account } from '../../account'; -import type { GqlGasCosts } from '../__generated__/operations'; import type { Coin } from '../coin'; import type { CoinQuantity, CoinQuantityLike } from '../coin-quantity'; import { coinQuantityfy } from '../coin-quantity'; import type { MessageCoin } from '../message'; -import type { ChainInfo } from '../provider'; +import type { ChainInfo, GasCosts } from '../provider'; import type { Resource } from '../resource'; import { isCoin } from '../resource'; import { normalizeJSON } from '../utils'; @@ -517,7 +516,7 @@ export abstract class BaseTransactionRequest implements BaseTransactionRequestLi /** * @hidden */ - metadataGas(_gasCosts: GqlGasCosts): BN { + metadataGas(_gasCosts: GasCosts): BN { throw new Error('Not implemented'); } @@ -525,8 +524,11 @@ export abstract class BaseTransactionRequest implements BaseTransactionRequestLi * @hidden */ calculateMinGas(chainInfo: ChainInfo): BN { - const { gasCosts, consensusParameters } = chainInfo; - const { gasPerByte } = consensusParameters; + const { consensusParameters } = chainInfo; + const { + gasCosts, + feeParameters: { gasPerByte }, + } = consensusParameters; return getMinGas({ gasPerByte, gasCosts, @@ -538,7 +540,10 @@ export abstract class BaseTransactionRequest implements BaseTransactionRequestLi calculateMaxGas(chainInfo: ChainInfo, minGas: BN): BN { const { consensusParameters } = chainInfo; - const { gasPerByte, maxGasPerTx } = consensusParameters; + const { + feeParameters: { gasPerByte }, + txParameters: { maxGasPerTx }, + } = consensusParameters; const witnessesLength = this.toTransaction().witnesses.reduce( (acc, wit) => acc + wit.dataLength, diff --git a/packages/account/src/providers/transaction-response/transaction-response.ts b/packages/account/src/providers/transaction-response/transaction-response.ts index b715cd90de..26a6214d8a 100644 --- a/packages/account/src/providers/transaction-response/transaction-response.ts +++ b/packages/account/src/providers/transaction-response/transaction-response.ts @@ -194,7 +194,7 @@ export class TransactionResponse { const { gasPerByte, gasPriceFactor, gasCosts, maxGasPerTx } = this.provider.getGasConfig(); const gasPrice = await this.provider.getLatestGasPrice(); - const maxInputs = this.provider.getChain().consensusParameters.maxInputs; + const maxInputs = this.provider.getChain().consensusParameters.txParameters.maxInputs; const transactionSummary = assembleTransactionSummary({ id: this.id, diff --git a/packages/account/src/providers/transaction-summary/assemble-transaction-summary.test.ts b/packages/account/src/providers/transaction-summary/assemble-transaction-summary.test.ts index 9c7234802a..1bd25198d8 100644 --- a/packages/account/src/providers/transaction-summary/assemble-transaction-summary.test.ts +++ b/packages/account/src/providers/transaction-summary/assemble-transaction-summary.test.ts @@ -14,12 +14,12 @@ import { MOCK_SUBMITTED_STATUS, MOCK_SQUEEZEDOUT_STATUS, } from '../../../test/fixtures/transaction-summary'; -import type { GqlGasCosts } from '../__generated__/operations'; +import type { GasCosts } from '../provider'; import Provider from '../provider'; import type { TransactionResultReceipt } from '../transaction-response'; import { assembleTransactionSummary } from './assemble-transaction-summary'; -import * as calculateTransactionFeeMod from './calculate-transaction-fee'; +import * as calculateTransactionFeeMod from './calculate-tx-fee-for-summary'; import type { GraphqlTransactionStatus, Operation } from './types'; /** @@ -27,7 +27,7 @@ import type { GraphqlTransactionStatus, Operation } from './types'; */ describe('TransactionSummary', () => { let provider: Provider; - let gasCosts: GqlGasCosts; + let gasCosts: GasCosts; const id = '0x2bfbebca58da94ba3ee258698c9be5884e2874688bdffa29cb535cf05d665215'; const gasPerByte = bn(2); @@ -46,7 +46,9 @@ describe('TransactionSummary', () => { beforeAll(async () => { provider = await Provider.create('http://127.0.0.1:4000/v1/graphql'); - gasCosts = provider.getChain().gasCosts; + ({ + consensusParameters: { gasCosts }, + } = provider.getChain()); }); beforeEach(() => { @@ -55,12 +57,8 @@ describe('TransactionSummary', () => { const mockCalculateTransactionFee = () => { const calculateTransactionFee = vi - .spyOn(calculateTransactionFeeMod, 'calculateTransactionFee') - .mockReturnValue({ - fee: bn(0), - minFee: bn(0), - maxFee: bn(0), - }); + .spyOn(calculateTransactionFeeMod, 'calculateTXFeeForSummary') + .mockReturnValue(bn(0)); return { calculateTransactionFee, diff --git a/packages/account/src/providers/transaction-summary/assemble-transaction-summary.ts b/packages/account/src/providers/transaction-summary/assemble-transaction-summary.ts index b1eca0ebc9..5540687283 100644 --- a/packages/account/src/providers/transaction-summary/assemble-transaction-summary.ts +++ b/packages/account/src/providers/transaction-summary/assemble-transaction-summary.ts @@ -2,17 +2,19 @@ import { bn, type BN } from '@fuel-ts/math'; import { PolicyType, type Transaction } from '@fuel-ts/transactions'; import { DateTime, hexlify } from '@fuel-ts/utils'; -import type { GqlGasCosts } from '../__generated__/operations'; +import type { GasCosts } from '../provider'; import type { TransactionResultReceipt } from '../transaction-response'; import { getGasUsedFromReceipts } from '../utils'; -import { calculateTransactionFee } from './calculate-transaction-fee'; +import { calculateTXFeeForSummary } from './calculate-tx-fee-for-summary'; import { getOperations, getTransactionTypeName, isTypeMint, isTypeCreate, isTypeScript, + isTypeUpgrade, + isTypeUpload, } from './operations'; import { extractBurnedAssetsFromReceipts, extractMintedAssetsFromReceipts } from './receipt'; import { processGraphqlStatus } from './status'; @@ -28,7 +30,7 @@ export interface AssembleTransactionSummaryParams { receipts: TransactionResultReceipt[]; abiMap?: AbiMap; maxInputs: BN; - gasCosts: GqlGasCosts; + gasCosts: GasCosts; maxGasPerTx: BN; gasPrice: BN; } @@ -70,7 +72,11 @@ export function assembleTransactionSummary( const tip = bn(transaction.policies?.find((policy) => policy.type === PolicyType.Tip)?.data); - const { fee } = calculateTransactionFee({ + const { isStatusFailure, isStatusPending, isStatusSuccess, blockId, status, time, totalFee } = + processGraphqlStatus(gqlTransactionStatus); + + const fee = calculateTXFeeForSummary({ + totalFee, gasPrice, rawPayload, tip, @@ -84,9 +90,6 @@ export function assembleTransactionSummary( }, }); - const { isStatusFailure, isStatusPending, isStatusSuccess, blockId, status, time } = - processGraphqlStatus(gqlTransactionStatus); - const mintedAssets = extractMintedAssetsFromReceipts(receipts); const burnedAssets = extractBurnedAssetsFromReceipts(receipts); @@ -98,6 +101,7 @@ export function assembleTransactionSummary( const transactionSummary: TransactionSummary = { id, + tip, fee, gasUsed, operations, @@ -111,6 +115,8 @@ export function assembleTransactionSummary( isTypeMint: isTypeMint(transaction.type), isTypeCreate: isTypeCreate(transaction.type), isTypeScript: isTypeScript(transaction.type), + isTypeUpgrade: isTypeUpgrade(transaction.type), + isTypeUpload: isTypeUpload(transaction.type), isStatusFailure, isStatusSuccess, isStatusPending, diff --git a/packages/account/src/providers/transaction-summary/calculate-transaction-fee.ts b/packages/account/src/providers/transaction-summary/calculate-tx-fee-for-summary.ts similarity index 79% rename from packages/account/src/providers/transaction-summary/calculate-transaction-fee.ts rename to packages/account/src/providers/transaction-summary/calculate-tx-fee-for-summary.ts index 224367c319..8a8c6bb5cf 100644 --- a/packages/account/src/providers/transaction-summary/calculate-transaction-fee.ts +++ b/packages/account/src/providers/transaction-summary/calculate-tx-fee-for-summary.ts @@ -4,7 +4,8 @@ import type { TransactionCreate, TransactionScript } from '@fuel-ts/transactions import { PolicyType, TransactionCoder, TransactionType } from '@fuel-ts/transactions'; import { arrayify } from '@fuel-ts/utils'; -import type { GqlConsensusParameters, GqlFeeParameters } from '../__generated__/operations'; +import type { GqlFeeParameters } from '../__generated__/operations'; +import type { ConsensusParameters } from '../provider'; import { calculateGasFee, calculateMetadataGasForTxCreate, @@ -20,24 +21,34 @@ type FeeParams = gasPriceFactor: BN | number; }; -export type CalculateTransactionFeeParams = { +export type CalculateTXFeeForSummaryParams = { gasPrice: BN; rawPayload: string; tip: BN; - consensusParameters: Pick & { + totalFee?: BN; + consensusParameters: Pick & { feeParams: FeeParams; maxGasPerTx: BN; }; }; -export const calculateTransactionFee = (params: CalculateTransactionFeeParams) => { +export const calculateTXFeeForSummary = (params: CalculateTXFeeForSummaryParams): BN => { const { gasPrice, rawPayload, tip, + totalFee, consensusParameters: { gasCosts, feeParams, maxGasPerTx }, } = params; + /** + * If totalFee is provided it means that the TX was already processed and we could extract the fee + * from its status + */ + if (totalFee) { + return totalFee; + } + const gasPerByte = bn(feeParams.gasPerByte); const gasPriceFactor = bn(feeParams.gasPriceFactor); @@ -45,14 +56,6 @@ export const calculateTransactionFee = (params: CalculateTransactionFeeParams) = const [transaction] = new TransactionCoder().decode(transactionBytes, 0); - if (transaction.type === TransactionType.Mint) { - return { - fee: bn(0), - minFee: bn(0), - maxFee: bn(0), - }; - } - const { type, witnesses, inputs, policies } = transaction as | TransactionCreate | TransactionScript; @@ -60,6 +63,10 @@ export const calculateTransactionFee = (params: CalculateTransactionFeeParams) = let metadataGas = bn(0); let gasLimit = bn(0); + if (type !== TransactionType.Create && type !== TransactionType.Script) { + return bn(0); + } + if (type === TransactionType.Create) { const { bytecodeWitnessIndex, storageSlots } = transaction as TransactionCreate; @@ -107,13 +114,6 @@ export const calculateTransactionFee = (params: CalculateTransactionFeeParams) = maxGasPerTx, }); - const minFee = calculateGasFee({ - gasPrice, - gas: minGas, - priceFactor: gasPriceFactor, - tip, - }); - const maxFee = calculateGasFee({ gasPrice, gas: maxGas, @@ -121,9 +121,5 @@ export const calculateTransactionFee = (params: CalculateTransactionFeeParams) = tip, }); - return { - minFee, - maxFee, - fee: maxFee, - }; + return maxFee; }; diff --git a/packages/account/src/providers/transaction-summary/calculate-transaction-fee.test.ts b/packages/account/src/providers/transaction-summary/calculate-tx-fee-for-summary.ts.test.ts similarity index 75% rename from packages/account/src/providers/transaction-summary/calculate-transaction-fee.test.ts rename to packages/account/src/providers/transaction-summary/calculate-tx-fee-for-summary.ts.test.ts index 94142fa124..54571c3dad 100644 --- a/packages/account/src/providers/transaction-summary/calculate-transaction-fee.test.ts +++ b/packages/account/src/providers/transaction-summary/calculate-tx-fee-for-summary.ts.test.ts @@ -7,7 +7,7 @@ import { MOCK_TX_SCRIPT_RAW_PAYLOAD, } from '../../../test/fixtures/transaction-summary'; -import { calculateTransactionFee } from './calculate-transaction-fee'; +import { calculateTXFeeForSummary } from './calculate-tx-fee-for-summary'; /** * @group node @@ -23,7 +23,7 @@ describe('calculateTransactionFee', () => { const gasPriceFactor = 92; const gasPerByte = 4; - const { fee, maxFee, minFee } = calculateTransactionFee({ + const fee = calculateTXFeeForSummary({ tip: bn(0), gasPrice: bn(1), consensusParameters: { @@ -38,12 +38,8 @@ describe('calculateTransactionFee', () => { }); const expectedfee = bn(84); - const expectedmaxFee = bn(84); - const expectedminFee = bn(77); expect(fee.toNumber()).toEqual(expectedfee.toNumber()); - expect(maxFee.toNumber()).toEqual(expectedmaxFee.toNumber()); - expect(minFee.toNumber()).toEqual(expectedminFee.toNumber()); }); it('should properly calculate the transaction fee (CREATE TX)', () => { @@ -56,7 +52,7 @@ describe('calculateTransactionFee', () => { const gasPriceFactor = 92; const gasPerByte = 4; - const { fee, maxFee, minFee } = calculateTransactionFee({ + const fee = calculateTXFeeForSummary({ tip: bn(0), gasPrice: bn(1), consensusParameters: { @@ -71,12 +67,8 @@ describe('calculateTransactionFee', () => { }); const expectedfee = bn(159); - const expectedmaxFee = bn(159); - const expectedminFee = bn(159); expect(fee.toNumber()).toEqual(expectedfee.toNumber()); - expect(maxFee.toNumber()).toEqual(expectedmaxFee.toNumber()); - expect(minFee.toNumber()).toEqual(expectedminFee.toNumber()); }); it('should properly calculate the transaction fee (MINT TX)', () => { @@ -89,7 +81,7 @@ describe('calculateTransactionFee', () => { const gasPriceFactor = 92; const gasPerByte = 4; - const { fee, maxFee, minFee } = calculateTransactionFee({ + const fee = calculateTXFeeForSummary({ tip: bn(0), gasPrice: bn(1), consensusParameters: { @@ -104,7 +96,5 @@ describe('calculateTransactionFee', () => { }); expect(fee.toNumber()).toEqual(0); - expect(maxFee.toNumber()).toEqual(0); - expect(minFee.toNumber()).toEqual(0); }); }); diff --git a/packages/account/src/providers/transaction-summary/get-transaction-summary.ts b/packages/account/src/providers/transaction-summary/get-transaction-summary.ts index 3268c50d1a..3b849b63e6 100644 --- a/packages/account/src/providers/transaction-summary/get-transaction-summary.ts +++ b/packages/account/src/providers/transaction-summary/get-transaction-summary.ts @@ -53,7 +53,11 @@ export async function getTransactionSummary( const receipts = txReceipts.map(processGqlReceipt); const { - consensusParameters: { gasPerByte, gasPriceFactor, maxInputs, gasCosts, maxGasPerTx }, + consensusParameters: { + feeParameters: { gasPerByte, gasPriceFactor }, + txParameters: { maxInputs, maxGasPerTx }, + gasCosts, + }, } = provider.getChain(); const gasPrice = await provider.getLatestGasPrice(); @@ -94,7 +98,7 @@ export async function getTransactionSummaryFromRequest( const { receipts } = await provider.call(transactionRequest); const { gasPerByte, gasPriceFactor, gasCosts, maxGasPerTx } = provider.getGasConfig(); - const maxInputs = provider.getChain().consensusParameters.maxInputs; + const maxInputs = provider.getChain().consensusParameters.txParameters.maxInputs; const transaction = transactionRequest.toTransaction(); const transactionBytes = transactionRequest.toTransactionBytes(); @@ -139,7 +143,11 @@ export async function getTransactionsSummaries( const { edges, pageInfo } = transactionsByOwner; const { - consensusParameters: { gasPerByte, gasPriceFactor, maxInputs, gasCosts, maxGasPerTx }, + consensusParameters: { + feeParameters: { gasPerByte, gasPriceFactor }, + txParameters: { maxInputs, maxGasPerTx }, + gasCosts, + }, } = provider.getChain(); const gasPrice = await provider.getLatestGasPrice(); diff --git a/packages/account/src/providers/transaction-summary/index.ts b/packages/account/src/providers/transaction-summary/index.ts index 44ccde04f1..00138ea40e 100644 --- a/packages/account/src/providers/transaction-summary/index.ts +++ b/packages/account/src/providers/transaction-summary/index.ts @@ -6,4 +6,4 @@ export * from './operations'; export * from './get-transaction-summary'; export * from './assemble-transaction-summary'; export * from './receipt'; -export * from './calculate-transaction-fee'; +export * from './calculate-tx-fee-for-summary'; diff --git a/packages/account/src/providers/transaction-summary/operations.ts b/packages/account/src/providers/transaction-summary/operations.ts index 08f8451e5a..747be5c9b0 100644 --- a/packages/account/src/providers/transaction-summary/operations.ts +++ b/packages/account/src/providers/transaction-summary/operations.ts @@ -85,6 +85,16 @@ export function isTypeScript(transactionType: TransactionType) { return isType(transactionType, TransactionTypeName.Script); } +/** @hidden */ +export function isTypeUpgrade(transactionType: TransactionType) { + return isType(transactionType, TransactionTypeName.Upgrade); +} + +/** @hidden */ +export function isTypeUpload(transactionType: TransactionType) { + return isType(transactionType, TransactionTypeName.Upload); +} + /** @hidden */ export function hasSameAssetId(a: OperationCoin) { return (b: OperationCoin) => a.assetId === b.assetId; diff --git a/packages/account/src/providers/transaction-summary/status.ts b/packages/account/src/providers/transaction-summary/status.ts index d913cc99a8..aa5c6ced2b 100644 --- a/packages/account/src/providers/transaction-summary/status.ts +++ b/packages/account/src/providers/transaction-summary/status.ts @@ -1,4 +1,5 @@ import { ErrorCode, FuelError } from '@fuel-ts/errors'; +import { bn, type BN } from '@fuel-ts/math'; import type { BlockId, @@ -31,13 +32,15 @@ export const getTransactionStatusName = (gqlStatus: GqlTransactionStatusesNames) type IProcessGraphqlStatusResponse = Pick< TransactionSummary, 'time' | 'blockId' | 'isStatusPending' | 'isStatusSuccess' | 'isStatusFailure' | 'status' ->; +> & { totalFee?: BN; totalGas?: BN }; /** @hidden */ export const processGraphqlStatus = (gqlTransactionStatus?: GraphqlTransactionStatus) => { let time: Time | undefined; let blockId: BlockId | undefined; let status: TransactionStatus | undefined; + let totalFee: BN | undefined; + let totalGas: BN | undefined; let isStatusFailure = false; let isStatusSuccess = false; @@ -51,12 +54,16 @@ export const processGraphqlStatus = (gqlTransactionStatus?: GraphqlTransactionSt time = gqlTransactionStatus.time; blockId = gqlTransactionStatus.block.id; isStatusSuccess = true; + totalFee = bn(gqlTransactionStatus.totalFee); + totalGas = bn(gqlTransactionStatus.totalGas); break; case 'FailureStatus': time = gqlTransactionStatus.time; blockId = gqlTransactionStatus.block.id; isStatusFailure = true; + totalFee = bn(gqlTransactionStatus.totalFee); + totalGas = bn(gqlTransactionStatus.totalGas); break; case 'SubmittedStatus': @@ -71,6 +78,8 @@ export const processGraphqlStatus = (gqlTransactionStatus?: GraphqlTransactionSt time, blockId, status, + totalFee, + totalGas, isStatusFailure, isStatusSuccess, isStatusPending, diff --git a/packages/account/src/providers/transaction-summary/types.ts b/packages/account/src/providers/transaction-summary/types.ts index 2b4e93954f..d657f6209d 100644 --- a/packages/account/src/providers/transaction-summary/types.ts +++ b/packages/account/src/providers/transaction-summary/types.ts @@ -30,6 +30,8 @@ export enum TransactionTypeName { Create = 'Create', Mint = 'Mint', Script = 'Script', + Upgrade = 'Upgrade', + Upload = 'Upload', } /** @@ -154,6 +156,7 @@ export type TransactionSummary = { time?: string; operations: Operation[]; gasUsed: BN; + tip: BN; fee: BN; type: TransactionTypeName; blockId?: BlockId; @@ -161,6 +164,8 @@ export type TransactionSummary = { isTypeMint: boolean; isTypeCreate: boolean; isTypeScript: boolean; + isTypeUpgrade: boolean; + isTypeUpload: boolean; isStatusPending: boolean; isStatusSuccess: boolean; isStatusFailure: boolean; diff --git a/packages/account/src/providers/utils/gas.ts b/packages/account/src/providers/utils/gas.ts index 08ff8d42f5..45020a7231 100644 --- a/packages/account/src/providers/utils/gas.ts +++ b/packages/account/src/providers/utils/gas.ts @@ -3,7 +3,8 @@ import type { BN, BNInput } from '@fuel-ts/math'; import { ReceiptType, type Input } from '@fuel-ts/transactions'; import { arrayify } from '@fuel-ts/utils'; -import type { GqlDependentCost, GqlGasCosts } from '../__generated__/operations'; +import type { GqlDependentCost } from '../__generated__/operations'; +import type { GasCosts } from '../provider'; import type { TransactionRequestInput } from '../transaction-request'; import type { TransactionResultReceipt, @@ -36,7 +37,7 @@ export function resolveGasDependentCosts(byteSize: BNInput, gasDependentCost: Gq export function gasUsedByInputs( inputs: Array, txBytesSize: number, - gasCosts: GqlGasCosts + gasCosts: GasCosts ) { const witnessCache: Array = []; @@ -75,7 +76,7 @@ export function gasUsedByInputs( export interface IGetMinGasParams { inputs: Array; - gasCosts: GqlGasCosts; + gasCosts: GasCosts; txBytesSize: number; metadataGas: BN; gasPerByte: BN; @@ -129,7 +130,7 @@ export function calculateMetadataGasForTxCreate({ txBytesSize, contractBytesSize, }: { - gasCosts: GqlGasCosts; + gasCosts: GasCosts; contractBytesSize: BN; stateRootSize: number; txBytesSize: number; @@ -148,7 +149,7 @@ export function calculateMetadataGasForTxScript({ gasCosts, txBytesSize, }: { - gasCosts: GqlGasCosts; + gasCosts: GasCosts; txBytesSize: number; }) { return resolveGasDependentCosts(txBytesSize, gasCosts.s256); diff --git a/packages/account/src/test-utils/launchNode.ts b/packages/account/src/test-utils/launchNode.ts index 1644195e6f..41a2ecc1f2 100644 --- a/packages/account/src/test-utils/launchNode.ts +++ b/packages/account/src/test-utils/launchNode.ts @@ -198,10 +198,12 @@ export const launchNode = async ({ const chainConfigWritePath = path.join(tempDirPath, 'chainConfig.json'); const stateConfigWritePath = path.join(tempDirPath, 'stateConfig.json'); const metadataWritePath = path.join(tempDirPath, 'metadata.json'); + const stateTransitionWritePath = path.join(tempDirPath, 'state_transition_bytecode.wasm'); writeFileSync(chainConfigWritePath, JSON.stringify(chainConfigJson), 'utf8'); writeFileSync(stateConfigWritePath, fixedStateConfigJSON, 'utf8'); writeFileSync(metadataWritePath, JSON.stringify(metadataJson), 'utf8'); + writeFileSync(stateTransitionWritePath, JSON.stringify('')); snapshotDirToUse = tempDirPath; } diff --git a/packages/account/src/test-utils/launchNodeAndGetWallets.test.ts b/packages/account/src/test-utils/launchNodeAndGetWallets.test.ts index b80751a6cb..18f5689968 100644 --- a/packages/account/src/test-utils/launchNodeAndGetWallets.test.ts +++ b/packages/account/src/test-utils/launchNodeAndGetWallets.test.ts @@ -36,7 +36,9 @@ describe('launchNode', () => { }); const { - consensusParameters: { gasPerByte }, + consensusParameters: { + feeParameters: { gasPerByte }, + }, } = provider.getChain(); const expectedGasPerByte = 63; diff --git a/packages/account/test/fixtures/chain.ts b/packages/account/test/fixtures/chain.ts index 80a2343cda..5b8cee69ed 100644 --- a/packages/account/test/fixtures/chain.ts +++ b/packages/account/test/fixtures/chain.ts @@ -24,6 +24,7 @@ export const MOCK_CHAIN: GqlChainInfoFragmentFragment = { maxWitnesses: '255', maxGasPerTx: '500000000', maxSize: '17825792', + maxBytecodeSubsections: '255', }, scriptParams: { __typename: 'ScriptParameters', diff --git a/packages/account/test/fixtures/messageProof.ts b/packages/account/test/fixtures/messageProof.ts index 922c0d3147..795e5fd88f 100644 --- a/packages/account/test/fixtures/messageProof.ts +++ b/packages/account/test/fixtures/messageProof.ts @@ -73,34 +73,38 @@ export const MESSAGE_PROOF: MessageProof = { messageBlockHeader: { id: MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.id, daHeight: bn(MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.daHeight), - transactionsCount: bn(MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.transactionsCount), + transactionsCount: Number(MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.transactionsCount), transactionsRoot: MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.transactionsRoot, height: bn(MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.height), prevRoot: MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.prevRoot, time: MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.time, applicationHash: MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.applicationHash, - messageReceiptCount: bn(MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.messageReceiptCount), - consensusParametersVersion: - MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.consensusParametersVersion, - stateTransitionBytecodeVersion: - MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.stateTransitionBytecodeVersion, + messageReceiptCount: Number(MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.messageReceiptCount), + consensusParametersVersion: Number( + MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.consensusParametersVersion + ), + stateTransitionBytecodeVersion: Number( + MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.stateTransitionBytecodeVersion + ), eventInboxRoot: MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.eventInboxRoot, messageOutboxRoot: MESSAGE_PROOF_RAW_RESPONSE.messageBlockHeader.messageOutboxRoot, }, commitBlockHeader: { id: MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.id, daHeight: bn(MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.daHeight), - transactionsCount: bn(MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.transactionsCount), + transactionsCount: Number(MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.transactionsCount), transactionsRoot: MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.transactionsRoot, height: bn(MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.height), prevRoot: MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.prevRoot, time: MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.time, applicationHash: MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.applicationHash, - messageReceiptCount: bn(MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.messageReceiptCount), - consensusParametersVersion: - MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.consensusParametersVersion, - stateTransitionBytecodeVersion: - MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.stateTransitionBytecodeVersion, + messageReceiptCount: Number(MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.messageReceiptCount), + consensusParametersVersion: Number( + MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.consensusParametersVersion + ), + stateTransitionBytecodeVersion: Number( + MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.stateTransitionBytecodeVersion + ), eventInboxRoot: MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.eventInboxRoot, messageOutboxRoot: MESSAGE_PROOF_RAW_RESPONSE.commitBlockHeader.messageOutboxRoot, }, diff --git a/packages/account/test/fixtures/transaction-summary.ts b/packages/account/test/fixtures/transaction-summary.ts index 6272f40821..50d422f01a 100644 --- a/packages/account/test/fixtures/transaction-summary.ts +++ b/packages/account/test/fixtures/transaction-summary.ts @@ -290,6 +290,8 @@ export const MOCK_SUCCESS_STATUS: SuccessStatus = { id: '0x123', }, receipts: [], + totalFee: '1000', + totalGas: '1000', }; export const MOCK_FAILURE_STATUS: FailureStatus = { @@ -302,6 +304,8 @@ export const MOCK_FAILURE_STATUS: FailureStatus = { reason: 'reason', time: '4611686020122012535', receipts: [], + totalFee: '1000', + totalGas: '1000', }; export const MOCK_SUBMITTED_STATUS: SubmittedStatus = { diff --git a/packages/fuel-core/VERSION b/packages/fuel-core/VERSION index 63082344eb..4e8f395fa5 100644 --- a/packages/fuel-core/VERSION +++ b/packages/fuel-core/VERSION @@ -1 +1 @@ -0.24.3 +0.26.0 diff --git a/packages/fuel-gauge/src/contract-factory.test.ts b/packages/fuel-gauge/src/contract-factory.test.ts index 24cc83798d..cc037c0f2f 100644 --- a/packages/fuel-gauge/src/contract-factory.test.ts +++ b/packages/fuel-gauge/src/contract-factory.test.ts @@ -1,3 +1,4 @@ +import type { TransactionResult } from '@fuel-ts/account'; import { generateTestWallet } from '@fuel-ts/account/test-utils'; import { FuelError, ErrorCode } from '@fuel-ts/errors'; import { expectToThrowFuelError } from '@fuel-ts/errors/test-utils'; @@ -54,7 +55,7 @@ describe('Contract Factory', () => { await contact.functions.initialize_counter(100).call(); const { transactionResult } = await contact.functions.increment_counter(1).call(); - expect(transactionResult).toEqual({ + expect(transactionResult).toEqual({ blockId: expect.stringMatching(/^0x/), receipts: expect.arrayContaining([expect.any(Object)]), status: expect.any(String), @@ -66,12 +67,15 @@ describe('Contract Factory', () => { isStatusSuccess: expect.any(Boolean), isTypeCreate: expect.any(Boolean), isTypeMint: expect.any(Boolean), + isTypeUpgrade: expect.any(Boolean), + isTypeUpload: expect.any(Boolean), isTypeScript: expect.any(Boolean), logs: expect.any(Array), date: expect.any(Date), mintedAssets: expect.any(Array), burnedAssets: expect.any(Array), time: expect.any(String), + tip: expect.any(BN), id: expect.any(String), gasUsed: expect.objectContaining({ words: expect.arrayContaining([expect.any(Number)]), diff --git a/packages/fuel-gauge/src/dry-run-multiple-txs.test.ts b/packages/fuel-gauge/src/dry-run-multiple-txs.test.ts index ea694c8f3d..55e325e4ac 100644 --- a/packages/fuel-gauge/src/dry-run-multiple-txs.test.ts +++ b/packages/fuel-gauge/src/dry-run-multiple-txs.test.ts @@ -126,34 +126,40 @@ describe('dry-run-multiple-txs', () => { expect(estimatedRequests[0]).toStrictEqual({ receipts: expect.any(Array), - dryrunStatus: { + dryRunStatus: { reason: expect.any(String), programState: { data: expect.any(String), returnType: 'REVERT', }, + totalFee: expect.any(String), + totalGas: expect.any(String), } as GqlDryRunFailureStatus, }); expect(estimatedRequests[1]).toStrictEqual({ receipts: expect.any(Array), - dryrunStatus: { + dryRunStatus: { reason: expect.any(String), programState: { data: expect.any(String), returnType: 'REVERT', }, + totalFee: expect.any(String), + totalGas: expect.any(String), } as GqlDryRunFailureStatus, }); expect(estimatedRequests[2]).toStrictEqual({ receipts: expect.any(Array), - dryrunStatus: { + dryRunStatus: { reason: expect.any(String), programState: { data: expect.any(String), returnType: 'REVERT', }, + totalFee: expect.any(String), + totalGas: expect.any(String), } as GqlDryRunFailureStatus, }); }); @@ -261,7 +267,7 @@ describe('dry-run-multiple-txs', () => { receipts: [], missingContractIds: [], outputVariables: 0, - dryrunStatus: undefined, + dryRunStatus: undefined, }); // request 2 we dry run it 4 times to add the 3 output variables @@ -269,7 +275,11 @@ describe('dry-run-multiple-txs', () => { receipts: expect.any(Array), missingContractIds: [], outputVariables: 3, - dryrunStatus: { programState: expect.any(Object) }, + dryRunStatus: { + programState: expect.any(Object), + totalFee: expect.any(String), + totalGas: expect.any(String), + }, }); // request 3 we dry run it 3 times to add the 2 output variables (1 was already present) @@ -277,7 +287,11 @@ describe('dry-run-multiple-txs', () => { receipts: expect.any(Array), missingContractIds: [], outputVariables: 2, - dryrunStatus: { programState: expect.any(Object) }, + dryRunStatus: { + programState: expect.any(Object), + totalFee: expect.any(String), + totalGas: expect.any(String), + }, }); // request 4 we dry run it 1 time because it has reveted @@ -285,7 +299,12 @@ describe('dry-run-multiple-txs', () => { receipts: expect.any(Array), missingContractIds: [], outputVariables: 0, - dryrunStatus: { reason: 'TransferZeroCoins', programState: expect.any(Object) }, + dryRunStatus: { + reason: 'TransferZeroCoins', + programState: expect.any(Object), + totalFee: expect.any(String), + totalGas: expect.any(String), + }, }); // request 5 we dry run it 2 times because to add the missing output contract @@ -293,7 +312,11 @@ describe('dry-run-multiple-txs', () => { receipts: expect.any(Array), missingContractIds: [logOtherContract.id.toB256()], outputVariables: 0, - dryrunStatus: { programState: expect.any(Object) }, + dryRunStatus: { + programState: expect.any(Object), + totalFee: expect.any(String), + totalGas: expect.any(String), + }, }); }); }); diff --git a/packages/fuel-gauge/src/fee.test.ts b/packages/fuel-gauge/src/fee.test.ts index 0292f41525..dcd3ece6a4 100644 --- a/packages/fuel-gauge/src/fee.test.ts +++ b/packages/fuel-gauge/src/fee.test.ts @@ -292,8 +292,8 @@ describe('Fee', () => { expectToBeInRange({ value: fee.toNumber(), - min: balanceDiff - 10, - max: balanceDiff + 10, + min: balanceDiff - 20, + max: balanceDiff + 20, }); }); }); diff --git a/packages/fuels/test/fixtures/project/.fuels/chainConfig.json b/packages/fuels/test/fixtures/project/.fuels/chainConfig.json index aebccd7fde..81083c0945 100644 --- a/packages/fuels/test/fixtures/project/.fuels/chainConfig.json +++ b/packages/fuels/test/fixtures/project/.fuels/chainConfig.json @@ -8,7 +8,8 @@ "max_outputs": 255, "max_witnesses": 255, "max_gas_per_tx": 30000000, - "max_size": 112640 + "max_size": 112640, + "max_bytecode_subsections": 256 } }, "predicate_params": { diff --git a/packages/program/package.json b/packages/program/package.json index ff2a61066b..f9157152b8 100644 --- a/packages/program/package.json +++ b/packages/program/package.json @@ -33,6 +33,6 @@ "@fuel-ts/math": "workspace:*", "@fuel-ts/transactions": "workspace:*", "@fuel-ts/utils": "workspace:*", - "@fuels/vm-asm": "0.42.1" + "@fuels/vm-asm": "0.49.0" } } diff --git a/packages/program/src/functions/base-invocation-scope.ts b/packages/program/src/functions/base-invocation-scope.ts index 588fcb02cc..22e714079d 100644 --- a/packages/program/src/functions/base-invocation-scope.ts +++ b/packages/program/src/functions/base-invocation-scope.ts @@ -88,14 +88,15 @@ export class BaseInvocationScope { */ protected get calls() { const provider = this.getProvider(); - const consensusParams = provider.getChain().consensusParameters; + const consensusParams = provider.getChain(); + // TODO: Remove this error since it is already handled on Provider class if (!consensusParams) { throw new FuelError( FuelError.CODES.CHAIN_INFO_CACHE_EMPTY, 'Provider chain info cache is empty. Please make sure to initialize the `Provider` properly by running `await Provider.create()``' ); } - const maxInputs = consensusParams.maxInputs; + const maxInputs = consensusParams.consensusParameters.txParameters.maxInputs; const script = getContractCallScript(this.functionInvocationScopes, maxInputs); return this.functionInvocationScopes.map((funcScope) => createContractCall(funcScope, script.getScriptDataOffset(maxInputs.toNumber())) @@ -106,7 +107,12 @@ export class BaseInvocationScope { * Updates the script request with the current contract calls. */ protected updateScriptRequest() { - const maxInputs = (this.program.provider as Provider).getChain().consensusParameters.maxInputs; + const provider = this.getProvider(); + const { + consensusParameters: { + txParameters: { maxInputs }, + }, + } = provider.getChain(); const contractCallScript = getContractCallScript(this.functionInvocationScopes, maxInputs); this.transactionRequest.setScript(contractCallScript, this.calls); } diff --git a/packages/script/src/script-invocation-scope.ts b/packages/script/src/script-invocation-scope.ts index ca92a472c1..c0edc84452 100644 --- a/packages/script/src/script-invocation-scope.ts +++ b/packages/script/src/script-invocation-scope.ts @@ -23,6 +23,7 @@ export class ScriptInvocationScope< const programBytes = (this.program as AbstractScript).bytes; const chainInfoCache = (this.program.provider as Provider).getChain(); + // TODO: Remove this error since it is already handled on Provider class if (!chainInfoCache) { throw new FuelError( FuelError.CODES.CHAIN_INFO_CACHE_EMPTY, @@ -30,7 +31,7 @@ export class ScriptInvocationScope< ); } - const maxInputs = chainInfoCache.consensusParameters.maxInputs.toNumber(); + const maxInputs = chainInfoCache.consensusParameters.txParameters.maxInputs.toNumber(); const byteLength = new ByteArrayCoder(programBytes.length).encodedLength; this.scriptRequest = new ScriptRequest( diff --git a/packages/transactions/src/coders/transaction.test.ts b/packages/transactions/src/coders/transaction.test.ts index 50b68cb9a9..c4ca284623 100644 --- a/packages/transactions/src/coders/transaction.test.ts +++ b/packages/transactions/src/coders/transaction.test.ts @@ -6,10 +6,12 @@ import { OutputType } from './output'; import { PolicyType } from './policy'; import type { Transaction } from './transaction'; import { TransactionCoder, TransactionType } from './transaction'; +import { UpgradePurposeTypeEnum } from './upgrade-purpose'; const B256 = '0xd5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b'; const U64 = bn(32); const U32 = 1000; +const U16 = 900; const U8 = 1; /** @@ -290,4 +292,243 @@ describe('TransactionCoder', () => { JSON.parse(JSON.stringify(transaction)) ); }); + + it('Can encode/decode TransactionUpgrade without inputs, outputs and witnesses', () => { + const transaction: Transaction = { + type: TransactionType.Upgrade, + upgradePurpose: { + type: UpgradePurposeTypeEnum.ConsensusParameters, + data: { + checksum: B256, + witnessIndex: U8, + }, + }, + policyTypes: 5, + inputsCount: 0, + outputsCount: 0, + witnessesCount: 0, + policies: [ + { type: PolicyType.Tip, data: bn(U32) }, + { type: PolicyType.Maturity, data: U32 }, + ], + inputs: [], + outputs: [], + witnesses: [], + }; + + const encoded = hexlify(new TransactionCoder().encode(transaction)); + + expect(encoded).toEqual( + '0x000000000000000300000000000000000000000000000001d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b000000000000000500000000000000000000000000000000000000000000000000000000000003e800000000000003e8' + ); + + const [decoded, offset] = new TransactionCoder().decode(arrayify(encoded), 0); + + expect(offset).toEqual((encoded.length - 2) / 2); + expect(JSON.parse(JSON.stringify(decoded))).toMatchObject( + JSON.parse(JSON.stringify(transaction)) + ); + }); + + it('Can encode/decode TransactionUpgrade with inputs, outputs and witnesses', () => { + const transaction: Transaction = { + type: TransactionType.Upgrade, + upgradePurpose: { + type: UpgradePurposeTypeEnum.StateTransition, + data: { + bytecodeRoot: B256, + }, + }, + policyTypes: 7, + inputsCount: 1, + outputsCount: 1, + witnessesCount: 3, + policies: [ + { type: PolicyType.Tip, data: bn(U32) }, + { type: PolicyType.WitnessLimit, data: bn(U32) }, + { type: PolicyType.Maturity, data: U32 }, + ], + inputs: [ + { + type: InputType.Contract, + txID: B256, + outputIndex: 0, + balanceRoot: B256, + stateRoot: B256, + contractID: B256, + txPointer: { + blockHeight: 0, + txIndex: 0, + }, + }, + ], + outputs: [ + { + type: OutputType.Coin, + to: B256, + amount: bn(1), + assetId: B256, + }, + ], + witnesses: [ + { + dataLength: 1, + data: '0x01', + }, + { + dataLength: 2, + data: '0x0101', + }, + { + dataLength: 3, + data: '0x010101', + }, + ], + }; + + const encoded = hexlify(new TransactionCoder().encode(transaction)); + + expect(encoded).toEqual( + '0x00000000000000030000000000000001d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b000000000000000700000000000000010000000000000001000000000000000300000000000003e800000000000003e800000000000003e80000000000000001d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000000d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930bd5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b00000000000000000000000000000000d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000000d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000001d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b000000000000000101000000000000000000000000000002010100000000000000000000000000030101010000000000' + ); + + const [decoded, offset] = new TransactionCoder().decode(arrayify(encoded), 0); + + expect(offset).toEqual((encoded.length - 2) / 2); + expect(JSON.parse(JSON.stringify(decoded))).toMatchObject( + JSON.parse(JSON.stringify(transaction)) + ); + }); + + it('Can encode/decode TransactionUpload without inputs, outputs and witnesses', () => { + const transaction: Transaction = { + type: TransactionType.Upload, + root: B256, + witnessIndex: U16, + subsectionIndex: U16, + subsectionsNumber: U16, + proofSetCount: 3, + policyTypes: 7, + inputsCount: 0, + outputsCount: 0, + witnessesCount: 0, + proofSet: [B256, B256, B256], + policies: [ + { type: PolicyType.Tip, data: bn(U32) }, + { type: PolicyType.WitnessLimit, data: bn(U32) }, + { type: PolicyType.Maturity, data: U32 }, + ], + inputs: [], + outputs: [], + witnesses: [], + }; + + const encoded = hexlify(new TransactionCoder().encode(transaction)); + + expect(encoded).toEqual( + '0x0000000000000004d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b00000000000003840000000000000384000000000000038400000000000000030000000000000007000000000000000000000000000000000000000000000000d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930bd5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930bd5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b00000000000003e800000000000003e800000000000003e8' + ); + + const [decoded, offset] = new TransactionCoder().decode(arrayify(encoded), 0); + + expect(offset).toEqual((encoded.length - 2) / 2); + expect(JSON.parse(JSON.stringify(decoded))).toMatchObject( + JSON.parse(JSON.stringify(transaction)) + ); + }); + + it('Can encode/decode TransactionUpload with inputs, outputs and witnesses', () => { + const transaction: Transaction = { + type: TransactionType.Upload, + root: B256, + witnessIndex: U16, + subsectionIndex: U16, + subsectionsNumber: U16, + proofSetCount: 5, + policyTypes: 15, + inputsCount: 2, + outputsCount: 2, + witnessesCount: 3, + proofSet: [B256, B256, B256, B256, B256], + policies: [ + { type: PolicyType.Tip, data: bn(U32) }, + { type: PolicyType.WitnessLimit, data: bn(U32) }, + { type: PolicyType.Maturity, data: U32 }, + { type: PolicyType.MaxFee, data: U64 }, + ], + inputs: [ + { + type: InputType.Coin, + txID: B256, + outputIndex: 0, + owner: B256, + amount: bn(0), + assetId: B256, + txPointer: { + blockHeight: 0, + txIndex: 0, + }, + witnessIndex: 0, + predicateGasUsed: bn(0), + predicateLength: bn(0), + predicateDataLength: bn(0), + predicate: '0x', + predicateData: '0x', + }, + { + type: InputType.Contract, + txID: B256, + outputIndex: 0, + balanceRoot: B256, + stateRoot: B256, + contractID: B256, + txPointer: { + blockHeight: 0, + txIndex: 0, + }, + }, + ], + outputs: [ + { + type: OutputType.Coin, + to: B256, + amount: bn(1), + assetId: B256, + }, + { + type: OutputType.Change, + to: B256, + amount: bn(1), + assetId: B256, + }, + ], + witnesses: [ + { + dataLength: 1, + data: '0x01', + }, + { + dataLength: 2, + data: '0x0101', + }, + { + dataLength: 3, + data: '0x010101', + }, + ], + }; + + const encoded = hexlify(new TransactionCoder().encode(transaction)); + + expect(encoded).toEqual( + '0x0000000000000004d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000384000000000000038400000000000003840000000000000005000000000000000f000000000000000200000000000000020000000000000003d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930bd5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930bd5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930bd5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930bd5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b00000000000003e800000000000003e800000000000003e800000000000000200000000000000000d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000000d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000000d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000000d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930bd5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b00000000000000000000000000000000d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000000d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000001d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000002d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000001d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b000000000000000101000000000000000000000000000002010100000000000000000000000000030101010000000000' + ); + + const [decoded, offset] = new TransactionCoder().decode(arrayify(encoded), 0); + + expect(offset).toEqual((encoded.length - 2) / 2); + expect(JSON.parse(JSON.stringify(decoded))).toMatchObject( + JSON.parse(JSON.stringify(transaction)) + ); + }); }); diff --git a/packages/transactions/src/coders/transaction.ts b/packages/transactions/src/coders/transaction.ts index bb92a3c19c..740f778a2e 100644 --- a/packages/transactions/src/coders/transaction.ts +++ b/packages/transactions/src/coders/transaction.ts @@ -16,6 +16,7 @@ import { StorageSlotCoder } from './storage-slot'; import type { StorageSlot } from './storage-slot'; import type { TxPointer } from './tx-pointer'; import { TxPointerCoder } from './tx-pointer'; +import { UpgradePurposeCoder, type UpgradePurpose } from './upgrade-purpose'; import type { Witness } from './witness'; import { WitnessCoder } from './witness'; @@ -23,6 +24,8 @@ export enum TransactionType /* u8 */ { Script = 0, Create = 1, Mint = 2, + Upgrade = 3, + Upload = 4, } export type TransactionScript = { @@ -175,6 +178,7 @@ export type TransactionCreate = { /** Number of witnesses (u16) */ witnessesCount: number; + /** List of inputs (StorageSlot[]) */ storageSlots: StorageSlot[]; @@ -342,12 +346,242 @@ export class TransactionMintCoder extends Coder { + constructor() { + super('TransactionUpgrade', 'struct TransactionUpgrade', 0); + } + + encode(value: TransactionUpgrade): Uint8Array { + const parts: Uint8Array[] = []; + + parts.push(new UpgradePurposeCoder().encode(value.upgradePurpose)); + parts.push(new NumberCoder('u32').encode(value.policyTypes)); + parts.push(new NumberCoder('u16').encode(value.inputsCount)); + parts.push(new NumberCoder('u16').encode(value.outputsCount)); + parts.push(new NumberCoder('u16').encode(value.witnessesCount)); + parts.push(new PoliciesCoder().encode(value.policies)); + parts.push(new ArrayCoder(new InputCoder(), value.inputsCount).encode(value.inputs)); + parts.push(new ArrayCoder(new OutputCoder(), value.outputsCount).encode(value.outputs)); + parts.push(new ArrayCoder(new WitnessCoder(), value.witnessesCount).encode(value.witnesses)); + + return concat(parts); + } + + decode(data: Uint8Array, offset: number): [TransactionUpgrade, number] { + let decoded; + let o = offset; + + [decoded, o] = new UpgradePurposeCoder().decode(data, o); + const upgradePurpose = decoded; + [decoded, o] = new NumberCoder('u32').decode(data, o); + const policyTypes = decoded; + [decoded, o] = new NumberCoder('u16').decode(data, o); + const inputsCount = decoded; + [decoded, o] = new NumberCoder('u16').decode(data, o); + const outputsCount = decoded; + [decoded, o] = new NumberCoder('u16').decode(data, o); + const witnessesCount = decoded; + [decoded, o] = new PoliciesCoder().decode(data, o, policyTypes); + const policies = decoded; + [decoded, o] = new ArrayCoder(new InputCoder(), inputsCount).decode(data, o); + const inputs = decoded; + [decoded, o] = new ArrayCoder(new OutputCoder(), outputsCount).decode(data, o); + const outputs = decoded; + [decoded, o] = new ArrayCoder(new WitnessCoder(), witnessesCount).decode(data, o); + const witnesses = decoded; + + return [ + { + type: TransactionType.Upgrade, + upgradePurpose, + policyTypes, + inputsCount, + outputsCount, + witnessesCount, + policies, + inputs, + outputs, + witnesses, + }, + o, + ]; + } +} + +export type TransactionUpload = { + type: TransactionType.Upload; + + /** The root of the Merkle tree is created over the bytecode. (b256) */ + root: string; + + /** Index of witness that authorizes spending the coin (u16) */ + witnessIndex: number; + + /** The index of the subsection of the bytecode. (u16) */ + subsectionIndex: number; + + /** The total number of subsections on which bytecode was divided. (u16) */ + subsectionsNumber: number; + + /** Number of Merkle nodes in the proof. (u16) */ + proofSetCount: number; + + /** Bitfield of used policy types (u32) */ + policyTypes: number; + + /** Number of inputs (u16) */ + inputsCount: number; + + /** Number of outputs (u16) */ + outputsCount: number; + + /** Number of witnesses (u16) */ + witnessesCount: number; + + /** The proof set of Merkle nodes to verify the connection of the subsection to the root. (b256[]) */ + proofSet: string[]; + + /** List of policies, sorted by PolicyType. */ + policies: Policy[]; + + /** List of inputs (Input[]) */ + inputs: Input[]; + + /** List of outputs (Output[]) */ + outputs: Output[]; + + /** List of witnesses (Witness[]) */ + witnesses: Witness[]; +}; + +export class TransactionUploadCoder extends Coder { + constructor() { + super('TransactionUpload', 'struct TransactionUpload', 0); + } + + encode(value: TransactionUpload): Uint8Array { + const parts: Uint8Array[] = []; + + parts.push(new B256Coder().encode(value.root)); + parts.push(new NumberCoder('u16').encode(value.witnessIndex)); + parts.push(new NumberCoder('u16').encode(value.subsectionIndex)); + parts.push(new NumberCoder('u16').encode(value.subsectionsNumber)); + parts.push(new NumberCoder('u16').encode(value.proofSetCount)); + parts.push(new NumberCoder('u32').encode(value.policyTypes)); + parts.push(new NumberCoder('u16').encode(value.inputsCount)); + parts.push(new NumberCoder('u16').encode(value.outputsCount)); + parts.push(new NumberCoder('u16').encode(value.witnessesCount)); + parts.push(new ArrayCoder(new B256Coder(), value.proofSetCount).encode(value.proofSet)); + parts.push(new PoliciesCoder().encode(value.policies)); + parts.push(new ArrayCoder(new InputCoder(), value.inputsCount).encode(value.inputs)); + parts.push(new ArrayCoder(new OutputCoder(), value.outputsCount).encode(value.outputs)); + parts.push(new ArrayCoder(new WitnessCoder(), value.witnessesCount).encode(value.witnesses)); + + return concat(parts); + } + + decode(data: Uint8Array, offset: number): [TransactionUpload, number] { + let decoded; + let o = offset; + + [decoded, o] = new B256Coder().decode(data, o); + const root = decoded; + [decoded, o] = new NumberCoder('u16').decode(data, o); + const witnessIndex = decoded; + [decoded, o] = new NumberCoder('u16').decode(data, o); + const subsectionIndex = decoded; + [decoded, o] = new NumberCoder('u16').decode(data, o); + const subsectionsNumber = decoded; + [decoded, o] = new NumberCoder('u16').decode(data, o); + const proofSetCount = decoded; + [decoded, o] = new NumberCoder('u32').decode(data, o); + const policyTypes = decoded; + [decoded, o] = new NumberCoder('u16').decode(data, o); + const inputsCount = decoded; + [decoded, o] = new NumberCoder('u16').decode(data, o); + const outputsCount = decoded; + [decoded, o] = new NumberCoder('u16').decode(data, o); + const witnessesCount = decoded; + [decoded, o] = new ArrayCoder(new B256Coder(), proofSetCount).decode(data, o); + const proofSet = decoded; + [decoded, o] = new PoliciesCoder().decode(data, o, policyTypes); + const policies = decoded; + [decoded, o] = new ArrayCoder(new InputCoder(), inputsCount).decode(data, o); + const inputs = decoded; + [decoded, o] = new ArrayCoder(new OutputCoder(), outputsCount).decode(data, o); + const outputs = decoded; + [decoded, o] = new ArrayCoder(new WitnessCoder(), witnessesCount).decode(data, o); + const witnesses = decoded; + + return [ + { + type: TransactionType.Upload, + root, + witnessIndex, + subsectionIndex, + subsectionsNumber, + proofSetCount, + policyTypes, + inputsCount, + outputsCount, + witnessesCount, + proofSet, + policies, + inputs, + outputs, + witnesses, + }, + o, + ]; + } +} + +type PossibleTransactions = + | TransactionScript + | TransactionCreate + | TransactionMint + | TransactionUpgrade + | TransactionUpload; + export type Transaction = TTransactionType extends TransactionType ? Extract : Partial> & Partial> & - Partial> & { + Partial> & + Partial> & + Partial> & { type: TransactionType; }; @@ -380,6 +614,18 @@ export class TransactionCoder extends Coder { parts.push(new TransactionMintCoder().encode(value as Transaction)); break; } + case TransactionType.Upgrade: { + parts.push( + new TransactionUpgradeCoder().encode(value as Transaction) + ); + break; + } + case TransactionType.Upload: { + parts.push( + new TransactionUploadCoder().encode(value as Transaction) + ); + break; + } default: { throw new FuelError( ErrorCode.INVALID_TRANSACTION_TYPE, @@ -411,6 +657,14 @@ export class TransactionCoder extends Coder { [decoded, o] = new TransactionMintCoder().decode(data, o); return [decoded, o]; } + case TransactionType.Upgrade: { + [decoded, o] = new TransactionUpgradeCoder().decode(data, o); + return [decoded, o]; + } + case TransactionType.Upload: { + [decoded, o] = new TransactionUploadCoder().decode(data, o); + return [decoded, o]; + } default: { throw new FuelError( ErrorCode.INVALID_TRANSACTION_TYPE, diff --git a/packages/transactions/src/coders/upgrade-purpose.test.ts b/packages/transactions/src/coders/upgrade-purpose.test.ts new file mode 100644 index 0000000000..4bff302e37 --- /dev/null +++ b/packages/transactions/src/coders/upgrade-purpose.test.ts @@ -0,0 +1,81 @@ +import { B256Coder, NumberCoder } from '@fuel-ts/abi-coder'; +import { arrayify } from '@fuel-ts/utils'; + +import type { UpgradePurpose } from './upgrade-purpose'; +import { UpgradePurposeCoder, UpgradePurposeTypeEnum } from './upgrade-purpose'; + +/** + * @group node + * @group browser + */ +describe('UpgradePurposeCoder', () => { + const bytecodeRoot = '0x4dd439ec50a1caa950456cefb548043d144681e99361ab9ca6939fc5e466bde0'; + const checksum = '0xc343ed6a0396c31c21bcbd77f24fb0300ab6fcbb177da5cbd0b34c8695e72d2d'; + const witnessIndex = 2; + + it('can encode UpgradePurpose [ConsensusParameters]', () => { + const upgradePurpose: UpgradePurpose = { + type: UpgradePurposeTypeEnum.ConsensusParameters, + data: { + witnessIndex, + checksum, + }, + }; + + const typeBytes = [0, 0, 0, 0, 0, 0, 0, UpgradePurposeTypeEnum.ConsensusParameters]; + const witnessIndexBytes = new NumberCoder('u8').encode(witnessIndex); + const checksumBytes = new B256Coder().encode(checksum); + + const expectedEncoded = Uint8Array.from([...typeBytes, ...witnessIndexBytes, ...checksumBytes]); + + const encoded = new UpgradePurposeCoder().encode(upgradePurpose); + + expect(encoded).toStrictEqual(expectedEncoded); + }); + + it('can encode UpgradePurpose [StateTransition]', () => { + const upgradePurpose: UpgradePurpose = { + type: UpgradePurposeTypeEnum.StateTransition, + data: { + bytecodeRoot, + }, + }; + + const typeBytes = [0, 0, 0, 0, 0, 0, 0, UpgradePurposeTypeEnum.StateTransition]; + const bytecodeRootBytes = new B256Coder().encode(bytecodeRoot); + const expectedEncoded = Uint8Array.from([...typeBytes, ...bytecodeRootBytes]); + + const encoded = new UpgradePurposeCoder().encode(upgradePurpose); + + expect(encoded).toStrictEqual(expectedEncoded); + }); + + it('can decode UpgradePurpose [ConsensusParameters]', () => { + const encodedHex = + '0x00000000000000000000000000000002c343ed6a0396c31c21bcbd77f24fb0300ab6fcbb177da5cbd0b34c8695e72d2d'; + + const [upgradePurpose] = new UpgradePurposeCoder().decode(arrayify(encodedHex), 0); + + expect(upgradePurpose).toStrictEqual({ + type: UpgradePurposeTypeEnum.ConsensusParameters, + data: { + witnessIndex, + checksum, + }, + }); + }); + + it('can decode UpgradePurpose [StateTransition]', () => { + const encodedHex = + '0x00000000000000014dd439ec50a1caa950456cefb548043d144681e99361ab9ca6939fc5e466bde0'; + + const [upgradePurpose] = new UpgradePurposeCoder().decode(arrayify(encodedHex), 0); + + expect(upgradePurpose).toStrictEqual({ + type: UpgradePurposeTypeEnum.StateTransition, + data: { + bytecodeRoot, + }, + }); + }); +}); diff --git a/packages/transactions/src/coders/upgrade-purpose.ts b/packages/transactions/src/coders/upgrade-purpose.ts new file mode 100644 index 0000000000..1544033e26 --- /dev/null +++ b/packages/transactions/src/coders/upgrade-purpose.ts @@ -0,0 +1,103 @@ +import { B256Coder, Coder, NumberCoder } from '@fuel-ts/abi-coder'; +import { ErrorCode, FuelError } from '@fuel-ts/errors'; +import { concat } from '@fuel-ts/utils'; + +export enum UpgradePurposeTypeEnum { + ConsensusParameters = 0, + StateTransition = 1, +} + +export type UpgradePurpose = + | { + type: UpgradePurposeTypeEnum.ConsensusParameters; + data: ConsensusParameters; + } + | { + type: UpgradePurposeTypeEnum.StateTransition; + data: StateTransition; + }; + +export interface ConsensusParameters { + /** Index of witness that contains a serialized(with postcard) consensus parameters. (u16) */ + witnessIndex: number; + + /** The hash of the serialized consensus parameters. */ + checksum: string; +} + +export interface StateTransition { + /** The root of the new bytecode of the state transition function. */ + bytecodeRoot: string; +} + +export class UpgradePurposeCoder extends Coder { + constructor() { + super('UpgradePurpose', 'UpgradePurpose', 0); + } + + encode(upgradePurposeType: UpgradePurpose): Uint8Array { + const parts: Uint8Array[] = []; + const { type } = upgradePurposeType; + + parts.push(new NumberCoder('u8').encode(type)); + + switch (type) { + case UpgradePurposeTypeEnum.ConsensusParameters: { + const data = upgradePurposeType.data as ConsensusParameters; + + parts.push(new NumberCoder('u16').encode(data.witnessIndex)); + parts.push(new B256Coder().encode(data.checksum)); + break; + } + + case UpgradePurposeTypeEnum.StateTransition: { + const data = upgradePurposeType.data as StateTransition; + + parts.push(new B256Coder().encode(data.bytecodeRoot)); + break; + } + + default: { + throw new FuelError( + ErrorCode.INVALID_TRANSACTION_TYPE, + `Invalid transaction type: ${type}` + ); + } + } + + return concat(parts); + } + + decode(data: Uint8Array, offset: number): [UpgradePurpose, number] { + let o = offset; + let decoded; + + [decoded, o] = new NumberCoder('u8').decode(data, o); + const type = decoded as UpgradePurposeTypeEnum; + + switch (type) { + case UpgradePurposeTypeEnum.ConsensusParameters: { + [decoded, o] = new NumberCoder('u16').decode(data, o); + const witnessIndex = decoded; + [decoded, o] = new B256Coder().decode(data, o); + const checksum = decoded; + + return [{ type, data: { witnessIndex, checksum } }, o]; + } + + case UpgradePurposeTypeEnum.StateTransition: { + [decoded, o] = new B256Coder().decode(data, o); + const bytecodeRoot = decoded; + + return [{ type, data: { bytecodeRoot } }, o]; + } + + default: { + throw new FuelError( + ErrorCode.INVALID_TRANSACTION_TYPE, + `Invalid transaction type: ${type}` + ); + } + } + } +} diff --git a/packages/utils/src/utils/defaultSnapshots/chainConfig.json b/packages/utils/src/utils/defaultSnapshots/chainConfig.json index aebccd7fde..81083c0945 100644 --- a/packages/utils/src/utils/defaultSnapshots/chainConfig.json +++ b/packages/utils/src/utils/defaultSnapshots/chainConfig.json @@ -8,7 +8,8 @@ "max_outputs": 255, "max_witnesses": 255, "max_gas_per_tx": 30000000, - "max_size": 112640 + "max_size": 112640, + "max_bytecode_subsections": 256 } }, "predicate_params": { diff --git a/packages/utils/src/utils/defaultSnapshots/state_transition_bytecode.wasm b/packages/utils/src/utils/defaultSnapshots/state_transition_bytecode.wasm new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/versions/src/lib/getBuiltinVersions.ts b/packages/versions/src/lib/getBuiltinVersions.ts index 14c1ae69a9..ed10c4d97d 100644 --- a/packages/versions/src/lib/getBuiltinVersions.ts +++ b/packages/versions/src/lib/getBuiltinVersions.ts @@ -1,7 +1,7 @@ export function getBuiltinVersions() { return { FORC: '0.56.0', - FUEL_CORE: '0.24.3', + FUEL_CORE: '0.26.0', FUELS: '0.83.0', }; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2124b13f88..d34254d556 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -250,8 +250,8 @@ importers: apps/demo-nextjs: dependencies: '@fuels/vm-asm': - specifier: 0.42.1 - version: 0.42.1 + specifier: 0.49.0 + version: 0.49.0 '@types/node': specifier: 18.15.3 version: 18.15.3 @@ -286,8 +286,8 @@ importers: apps/demo-react-cra: dependencies: '@fuels/vm-asm': - specifier: 0.42.1 - version: 0.42.1 + specifier: 0.49.0 + version: 0.49.0 '@testing-library/react': specifier: ^13.4.0 version: 13.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -329,8 +329,8 @@ importers: apps/demo-react-vite: dependencies: '@fuels/vm-asm': - specifier: 0.42.1 - version: 0.42.1 + specifier: 0.49.0 + version: 0.49.0 fuels: specifier: workspace:* version: link:../../packages/fuels @@ -671,8 +671,8 @@ importers: specifier: workspace:* version: link:../versions '@fuels/vm-asm': - specifier: 0.42.1 - version: 0.42.1 + specifier: 0.49.0 + version: 0.49.0 '@noble/curves': specifier: ^1.3.0 version: 1.3.0 @@ -1031,8 +1031,8 @@ importers: specifier: workspace:* version: link:../utils '@fuels/vm-asm': - specifier: 0.42.1 - version: 0.42.1 + specifier: 0.49.0 + version: 0.49.0 packages/script: dependencies: @@ -2956,8 +2956,8 @@ packages: fuels: '>=0.74.0' react: ^18.2.0 - '@fuels/vm-asm@0.42.1': - resolution: {integrity: sha512-5e0IDHen26hrKc93ejYNDhQFbqi+EQ7xPpFJcUnSrz0+6zPdPhA2dtwh5UqN0fYDM5AcEFd0wpq+r7Pd2XS5AQ==} + '@fuels/vm-asm@0.49.0': + resolution: {integrity: sha512-IL+X9XoTlmomgSKO1pp8IThD/dcQo4Mz3dmCqRcY5+I9ux25P2apPCHxYLFx9m5bPJlQTm6VKbeVLMSdhr9nOw==} '@graphql-codegen/cli@2.13.7': resolution: {integrity: sha512-Rpk4WWrDgkDoVELftBr7/74MPiYmCITEF2+AWmyZZ2xzaC9cO2PqzZ+OYDEBNWD6UEk0RrIfVSa+slDKjhY59w==} @@ -14310,7 +14310,7 @@ snapshots: - '@types/react-dom' - react-dom - '@fuels/vm-asm@0.42.1': {} + '@fuels/vm-asm@0.49.0': {} '@graphql-codegen/cli@2.13.7(@babel/core@7.22.5)(@types/node@20.11.13)(enquirer@2.3.6)(graphql@16.8.1)(ts-node@10.9.1(@types/node@20.11.13)(typescript@5.2.2))(typescript@5.2.2)': dependencies: diff --git a/scripts/run-node.sh b/scripts/run-node.sh index 5737a41e59..3cc6d7b23a 100755 --- a/scripts/run-node.sh +++ b/scripts/run-node.sh @@ -8,6 +8,7 @@ mkdir -p .fuel-core/db cp ./packages/utils/src/utils/defaultSnapshots/chainConfig.json .fuel-core/configs/chainConfig.json cp ./packages/utils/src/utils/defaultSnapshots/metadata.json .fuel-core/configs/metadata.json cp ./packages/utils/src/utils/defaultSnapshots/stateConfig.json .fuel-core/configs/stateConfig.json +cp ./packages/utils/src/utils/defaultSnapshots/state_transition_bytecode.wasm .fuel-core/configs/state_transition_bytecode.wasm pnpm fuels-core run \ --db-path .fuel-core/db \