From f18ba32f065f4169688353e87c3af778cc457d98 Mon Sep 17 00:00:00 2001 From: Ahmed Sagdati <37515857+segfault-magnet@users.noreply.github.com> Date: Tue, 12 Nov 2024 00:29:06 +0700 Subject: [PATCH 1/4] bug: gql schema file missing (#1544) --- .github/workflows/ci.yml | 17 +- _typos.toml | 2 + e2e/tests/providers.rs | 6 +- packages/fuels-accounts/Cargo.toml | 4 - packages/fuels-accounts/build.rs | 15 - packages/fuels-accounts/src/lib.rs | 12 + .../src/provider/retryable_client.rs | 4 +- packages/fuels-accounts/src/schema/schema.sdl | 1299 +++++++++++++++++ 8 files changed, 1328 insertions(+), 31 deletions(-) create mode 100644 _typos.toml delete mode 100644 packages/fuels-accounts/build.rs create mode 100644 packages/fuels-accounts/src/schema/schema.sdl diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3b869082..b6bf6e2ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -252,14 +252,15 @@ jobs: if: ${{ matrix.command == 'test_wasm' }} uses: actions/setup-node@v3 with: - node-version: 18 - - - name: Test WASM - if: ${{ matrix.command == 'test_wasm' }} - run: | - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - cd wasm-tests - wasm-pack test --node + node-version: 22.8.0 + + # Until we fix the "missing env error" + # - name: Test WASM + # if: ${{ matrix.command == 'test_wasm' }} + # run: | + # curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + # cd wasm-tests + # wasm-pack test --node - name: Check that fuel_core version.rs file is up to date if: ${{ matrix.command == 'check_fuel_core_version' }} diff --git a/_typos.toml b/_typos.toml new file mode 100644 index 000000000..d991235a6 --- /dev/null +++ b/_typos.toml @@ -0,0 +1,2 @@ +[files] +extend-exclude = ["packages/fuels-accounts/src/schema/schema.sdl"] diff --git a/e2e/tests/providers.rs b/e2e/tests/providers.rs index cd7b289fd..74d47cc8c 100644 --- a/e2e/tests/providers.rs +++ b/e2e/tests/providers.rs @@ -9,7 +9,6 @@ use fuels::{ prelude::*, tx::Receipt, types::{ - block::Block, coin_type::CoinType, message::Message, transaction_builders::{BuildableTransaction, ScriptTransactionBuilder}, @@ -218,6 +217,9 @@ async fn can_increase_block_height() -> Result<()> { Ok(()) } +// debug builds are slower (20x for `fuel-core-lib`, 4x for a release-fuel-core-binary), makes for +// flaky tests +#[cfg(not(feature = "fuel-core-lib"))] #[tokio::test] async fn can_set_custom_block_time() -> Result<()> { // ANCHOR: use_produce_blocks_custom_time @@ -255,7 +257,7 @@ async fn can_set_custom_block_time() -> Result<()> { results: 10, direction: PageDirection::Forward, }; - let blocks: Vec = provider.get_blocks(req).await?.results; + let blocks: Vec = provider.get_blocks(req).await?.results; assert_eq!(blocks[1].header.time.unwrap().timestamp(), 20); assert_eq!(blocks[2].header.time.unwrap().timestamp(), 40); diff --git a/packages/fuels-accounts/Cargo.toml b/packages/fuels-accounts/Cargo.toml index 34dea20b8..866e94ff2 100644 --- a/packages/fuels-accounts/Cargo.toml +++ b/packages/fuels-accounts/Cargo.toml @@ -34,10 +34,6 @@ fuel-tx = { workspace = true, features = ["test-helpers", "random"] } tempfile = { workspace = true } tokio = { workspace = true, features = ["test-util"] } -[build-dependencies] -cynic = { workspace = true, features = ["default"], optional = true } -fuel-core-client = { workspace = true, optional = true } - [features] default = ["std"] coin-cache = ["tokio?/time"] diff --git a/packages/fuels-accounts/build.rs b/packages/fuels-accounts/build.rs deleted file mode 100644 index 4314a65b2..000000000 --- a/packages/fuels-accounts/build.rs +++ /dev/null @@ -1,15 +0,0 @@ -fn main() { - #[cfg(feature = "std")] - { - use std::fs; - - fs::create_dir_all("target").expect("Unable to create target directory"); - fs::write( - "target/fuel-core-client-schema.sdl", - fuel_core_client::SCHEMA_SDL, - ) - .expect("Unable to write schema file"); - - println!("cargo:rerun-if-changed=build.rs"); - } -} diff --git a/packages/fuels-accounts/src/lib.rs b/packages/fuels-accounts/src/lib.rs index b11d285f9..7bd1b1316 100644 --- a/packages/fuels-accounts/src/lib.rs +++ b/packages/fuels-accounts/src/lib.rs @@ -16,3 +16,15 @@ pub use account::*; mod coin_cache; pub mod predicate; + +#[cfg(test)] +mod test { + #[test] + fn sdl_is_the_same_as_from_fuel() { + let file_sdl = include_str!("./schema/schema.sdl"); + + let core_sdl = String::from_utf8(fuel_core_client::SCHEMA_SDL.to_vec()).unwrap(); + + assert_eq!(file_sdl, &core_sdl); + } +} diff --git a/packages/fuels-accounts/src/provider/retryable_client.rs b/packages/fuels-accounts/src/provider/retryable_client.rs index 69afc9bbf..06952e532 100644 --- a/packages/fuels-accounts/src/provider/retryable_client.rs +++ b/packages/fuels-accounts/src/provider/retryable_client.rs @@ -366,7 +366,7 @@ mod custom_queries { #[cynic( graphql_type = "Query", variables = "IsUserAccountVariables", - schema_path = "./target/fuel-core-client-schema.sdl" + schema_path = "./src/schema/schema.sdl" )] pub struct IsUserAccountQuery { #[arguments(id: $blob_id)] @@ -379,7 +379,7 @@ mod custom_queries { #[derive(cynic::QueryFragment, Clone, Debug)] #[cynic( - schema_path = "./target/fuel-core-client-schema.sdl", + schema_path = "./src/schema/schema.sdl", graphql_type = "Query", variables = "ContractByIdArgs" )] diff --git a/packages/fuels-accounts/src/schema/schema.sdl b/packages/fuels-accounts/src/schema/schema.sdl new file mode 100644 index 000000000..b9048362c --- /dev/null +++ b/packages/fuels-accounts/src/schema/schema.sdl @@ -0,0 +1,1299 @@ +scalar Address + +scalar AssetId + +type Balance { + owner: Address! + amount: U64! + assetId: AssetId! +} + +type BalanceConnection { + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + """ + A list of edges. + """ + edges: [BalanceEdge!]! + """ + A list of nodes. + """ + nodes: [Balance!]! +} + +""" +An edge in a connection. +""" +type BalanceEdge { + """ + The item at the end of the edge + """ + node: Balance! + """ + A cursor for use in pagination + """ + cursor: String! +} + +input BalanceFilterInput { + """ + Filter coins based on the `owner` field + """ + owner: Address! +} + +type Blob { + id: BlobId! + bytecode: HexString! +} + +scalar BlobId + +type Block { + version: BlockVersion! + id: BlockId! + height: U32! + header: Header! + consensus: Consensus! + transactionIds: [TransactionId!]! + transactions: [Transaction!]! +} + +type BlockConnection { + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + """ + A list of edges. + """ + edges: [BlockEdge!]! + """ + A list of nodes. + """ + nodes: [Block!]! +} + +""" +An edge in a connection. +""" +type BlockEdge { + """ + The item at the end of the edge + """ + node: Block! + """ + A cursor for use in pagination + """ + cursor: String! +} + +scalar BlockId + +enum BlockVersion { + V1 +} + + +""" +Breakpoint, defined as a tuple of contract ID and relative PC offset inside it +""" +input Breakpoint { + contract: ContractId! + pc: U64! +} + +scalar Bytes32 + +type ChainInfo { + name: String! + latestBlock: Block! + daHeight: U64! + consensusParameters: ConsensusParameters! + gasCosts: GasCosts! +} + +type ChangeOutput { + to: Address! + amount: U64! + assetId: AssetId! +} + +type Coin { + utxoId: UtxoId! + owner: Address! + amount: U64! + assetId: AssetId! + """ + TxPointer - the height of the block this coin was created in + """ + blockCreated: U32! + """ + TxPointer - the index of the transaction that created this coin + """ + txCreatedIdx: U16! +} + +type CoinConnection { + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + """ + A list of edges. + """ + edges: [CoinEdge!]! + """ + A list of nodes. + """ + nodes: [Coin!]! +} + +""" +An edge in a connection. +""" +type CoinEdge { + """ + The item at the end of the edge + """ + node: Coin! + """ + A cursor for use in pagination + """ + cursor: String! +} + +input CoinFilterInput { + """ + Returns coins owned by the `owner`. + """ + owner: Address! + """ + Returns coins only with `asset_id`. + """ + assetId: AssetId +} + +type CoinOutput { + to: Address! + amount: U64! + assetId: AssetId! +} + +""" +The schema analog of the [`coins::CoinType`]. +""" +union CoinType = Coin | MessageCoin + +union Consensus = Genesis | PoAConsensus + +type ConsensusParameters { + version: ConsensusParametersVersion! + txParams: TxParameters! + predicateParams: PredicateParameters! + scriptParams: ScriptParameters! + contractParams: ContractParameters! + feeParams: FeeParameters! + baseAssetId: AssetId! + blockGasLimit: U64! + blockTransactionSizeLimit: U64! + chainId: U64! + gasCosts: GasCosts! + privilegedAddress: Address! +} + +type ConsensusParametersPurpose { + witnessIndex: U16! + checksum: Bytes32! +} + +enum ConsensusParametersVersion { + V1 +} + +type Contract { + id: ContractId! + bytecode: HexString! + salt: Salt! +} + +type ContractBalance { + contract: ContractId! + amount: U64! + assetId: AssetId! +} + +type ContractBalanceConnection { + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + """ + A list of edges. + """ + edges: [ContractBalanceEdge!]! + """ + A list of nodes. + """ + nodes: [ContractBalance!]! +} + +""" +An edge in a connection. +""" +type ContractBalanceEdge { + """ + The item at the end of the edge + """ + node: ContractBalance! + """ + A cursor for use in pagination + """ + cursor: String! +} + +input ContractBalanceFilterInput { + """ + Filter assets based on the `contractId` field + """ + contract: ContractId! +} + +type ContractCreated { + contract: ContractId! + stateRoot: Bytes32! +} + +scalar ContractId + +type ContractOutput { + inputIndex: U16! + balanceRoot: Bytes32! + stateRoot: Bytes32! +} + +type ContractParameters { + version: ContractParametersVersion! + contractMaxSize: U64! + maxStorageSlots: U64! +} + +enum ContractParametersVersion { + V1 +} + +type DaCompressedBlock { + bytes: HexString! +} + +union DependentCost = LightOperation | HeavyOperation + +type DryRunFailureStatus { + programState: ProgramState + reason: String! + receipts: [Receipt!]! + totalGas: U64! + totalFee: U64! +} + +type DryRunSuccessStatus { + programState: ProgramState + receipts: [Receipt!]! + totalGas: U64! + totalFee: U64! +} + +type DryRunTransactionExecutionStatus { + id: TransactionId! + status: DryRunTransactionStatus! + receipts: [Receipt!]! +} + +union DryRunTransactionStatus = DryRunSuccessStatus | DryRunFailureStatus + +type EstimateGasPrice { + gasPrice: U64! +} + +input ExcludeInput { + """ + Utxos to exclude from the selection. + """ + utxos: [UtxoId!]! + """ + Messages to exclude from the selection. + """ + messages: [Nonce!]! +} + +type FailureStatus { + transactionId: TransactionId! + blockHeight: U32! + block: Block! + transaction: Transaction! + time: Tai64Timestamp! + reason: String! + programState: ProgramState + receipts: [Receipt!]! + totalGas: U64! + totalFee: U64! +} + +type FeeParameters { + version: FeeParametersVersion! + gasPriceFactor: U64! + gasPerByte: U64! +} + +enum FeeParametersVersion { + V1 +} + + +type GasCosts { + version: GasCostsVersion! + add: U64! + addi: U64! + aloc: U64! + and: U64! + andi: U64! + bal: U64! + bhei: U64! + bhsh: U64! + burn: U64! + cb: U64! + cfei: U64! + cfsi: U64! + div: U64! + divi: U64! + ecr1: U64! + eck1: U64! + ed19: U64! + eq: U64! + exp: U64! + expi: U64! + flag: U64! + gm: U64! + gt: U64! + gtf: U64! + ji: U64! + jmp: U64! + jne: U64! + jnei: U64! + jnzi: U64! + jmpf: U64! + jmpb: U64! + jnzf: U64! + jnzb: U64! + jnef: U64! + jneb: U64! + lb: U64! + log: U64! + lt: U64! + lw: U64! + mint: U64! + mlog: U64! + modOp: U64! + modi: U64! + moveOp: U64! + movi: U64! + mroo: U64! + mul: U64! + muli: U64! + mldv: U64! + noop: U64! + not: U64! + or: U64! + ori: U64! + poph: U64! + popl: U64! + pshh: U64! + pshl: U64! + ret: U64! + rvrt: U64! + sb: U64! + sll: U64! + slli: U64! + srl: U64! + srli: U64! + srw: U64! + sub: U64! + subi: U64! + sw: U64! + sww: U64! + time: U64! + tr: U64! + tro: U64! + wdcm: U64! + wqcm: U64! + wdop: U64! + wqop: U64! + wdml: U64! + wqml: U64! + wddv: U64! + wqdv: U64! + wdmd: U64! + wqmd: U64! + wdam: U64! + wqam: U64! + wdmm: U64! + wqmm: U64! + xor: U64! + xori: U64! + alocDependentCost: DependentCost! + bldd: DependentCost + bsiz: DependentCost + cfe: DependentCost! + cfeiDependentCost: DependentCost! + call: DependentCost! + ccp: DependentCost! + croo: DependentCost! + csiz: DependentCost! + ed19DependentCost: DependentCost! + k256: DependentCost! + ldc: DependentCost! + logd: DependentCost! + mcl: DependentCost! + mcli: DependentCost! + mcp: DependentCost! + mcpi: DependentCost! + meq: DependentCost! + retd: DependentCost! + s256: DependentCost! + scwq: DependentCost! + smo: DependentCost! + srwq: DependentCost! + swwq: DependentCost! + contractRoot: DependentCost! + stateRoot: DependentCost! + vmInitialization: DependentCost! + newStoragePerByte: U64! +} + +enum GasCostsVersion { + V1 +} + +type Genesis { + """ + The chain configs define what consensus type to use, what settlement layer to use, + rules of block validity, etc. + """ + chainConfigHash: Bytes32! + """ + The Binary Merkle Tree root of all genesis coins. + """ + coinsRoot: Bytes32! + """ + The Binary Merkle Tree root of state, balances, contracts code hash of each contract. + """ + contractsRoot: Bytes32! + """ + 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 { + """ + Version of the header + """ + version: HeaderVersion! + """ + Hash of the header + """ + id: BlockId! + """ + The layer 1 height of messages and events to include since the last layer 1 block number. + """ + daHeight: U64! + """ + The version of the consensus parameters used to create this block. + """ + consensusParametersVersion: U32! + """ + The version of the state transition bytecode used to create this block. + """ + stateTransitionBytecodeVersion: U32! + """ + Number of transactions in this block. + """ + transactionsCount: U16! + """ + Number of message receipts in this block. + """ + messageReceiptCount: U32! + """ + Merkle root of transactions. + """ + transactionsRoot: Bytes32! + """ + Merkle root of message receipts in this block. + """ + messageOutboxRoot: Bytes32! + """ + Merkle root of inbox events in this block. + """ + eventInboxRoot: Bytes32! + """ + Fuel block height. + """ + height: U32! + """ + Merkle root of all previous block header hashes. + """ + prevRoot: Bytes32! + """ + The block producer time. + """ + time: Tai64Timestamp! + """ + Hash of the application header. + """ + applicationHash: Bytes32! +} + +enum HeaderVersion { + V1 +} + +type HeavyOperation { + base: U64! + gasPerUnit: U64! +} + +scalar HexString + + +union Input = InputCoin | InputContract | InputMessage + +type InputCoin { + utxoId: UtxoId! + owner: Address! + amount: U64! + assetId: AssetId! + txPointer: TxPointer! + witnessIndex: Int! + predicateGasUsed: U64! + predicate: HexString! + predicateData: HexString! +} + +type InputContract { + utxoId: UtxoId! + balanceRoot: Bytes32! + stateRoot: Bytes32! + txPointer: TxPointer! + contractId: ContractId! +} + +type InputMessage { + sender: Address! + recipient: Address! + amount: U64! + nonce: Nonce! + witnessIndex: U16! + predicateGasUsed: U64! + data: HexString! + predicate: HexString! + predicateData: HexString! +} + + +type LatestGasPrice { + gasPrice: U64! + blockHeight: U32! +} + +type LightOperation { + base: U64! + unitsPerGas: U64! +} + +type MerkleProof { + proofSet: [Bytes32!]! + proofIndex: U64! +} + +type Message { + amount: U64! + sender: Address! + recipient: Address! + nonce: Nonce! + data: HexString! + daHeight: U64! +} + +type MessageCoin { + sender: Address! + recipient: Address! + nonce: Nonce! + amount: U64! + assetId: AssetId! + daHeight: U64! +} + +type MessageConnection { + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + """ + A list of edges. + """ + edges: [MessageEdge!]! + """ + A list of nodes. + """ + nodes: [Message!]! +} + +""" +An edge in a connection. +""" +type MessageEdge { + """ + The item at the end of the edge + """ + node: Message! + """ + A cursor for use in pagination + """ + cursor: String! +} + +type MessageProof { + messageProof: MerkleProof! + blockProof: MerkleProof! + messageBlockHeader: Header! + commitBlockHeader: Header! + sender: Address! + recipient: Address! + nonce: Nonce! + amount: U64! + data: HexString! +} + +enum MessageState { + UNSPENT + SPENT + NOT_FOUND +} + +type MessageStatus { + state: MessageState! +} + +type Mutation { + """ + Initialize a new debugger session, returning its ID. + A new VM instance is spawned for each session. + The session is run in a separate database transaction, + on top of the most recent node state. + """ + startSession: ID! + """ + End debugger session. + """ + endSession(id: ID!): Boolean! + """ + Reset the VM instance to the initial state. + """ + reset(id: ID!): Boolean! + """ + Execute a single fuel-asm instruction. + """ + execute(id: ID!, op: String!): Boolean! + """ + Set single-stepping mode for the VM instance. + """ + setSingleStepping(id: ID!, enable: Boolean!): Boolean! + """ + Set a breakpoint for a VM instance. + """ + setBreakpoint(id: ID!, breakpoint: Breakpoint!): Boolean! + """ + Run a single transaction in given session until it + hits a breakpoint or completes. + """ + startTx(id: ID!, txJson: String!): RunResult! + """ + Resume execution of the VM instance after a breakpoint. + Runs until the next breakpoint or until the transaction completes. + """ + continueTx(id: ID!): RunResult! + """ + Execute a dry-run of multiple transactions using a fork of current state, no changes are committed. + """ + dryRun(txs: [HexString!]!, utxoValidation: Boolean, gasPrice: U64): [DryRunTransactionExecutionStatus!]! + """ + Submits transaction to the `TxPool`. + + Returns submitted transaction if the transaction is included in the `TxPool` without problems. + """ + submit(tx: HexString!): Transaction! + """ + Sequentially produces `blocks_to_produce` blocks. The first block starts with + `start_timestamp`. If the block production in the [`crate::service::Config`] is + `Trigger::Interval { block_time }`, produces blocks with `block_time ` intervals between + them. The `start_timestamp` is the timestamp in seconds. + """ + produceBlocks(startTimestamp: Tai64Timestamp, blocksToProduce: U32!): U32! +} + +type NodeInfo { + utxoValidation: Boolean! + vmBacktrace: Boolean! + maxTx: U64! + maxDepth: U64! + nodeVersion: String! + peers: [PeerInfo!]! +} + +scalar Nonce + +union Output = CoinOutput | ContractOutput | ChangeOutput | VariableOutput | ContractCreated + +""" +A separate `Breakpoint` type to be used as an output, as a single +type cannot act as both input and output type in async-graphql +""" +type OutputBreakpoint { + contract: ContractId! + pc: U64! +} + +""" +Information about pagination in a connection +""" +type PageInfo { + """ + When paginating backwards, are there more items? + """ + hasPreviousPage: Boolean! + """ + When paginating forwards, are there more items? + """ + hasNextPage: Boolean! + """ + When paginating backwards, the cursor to continue. + """ + startCursor: String + """ + When paginating forwards, the cursor to continue. + """ + endCursor: String +} + +type PeerInfo { + """ + The libp2p peer id + """ + id: String! + """ + The advertised multi-addrs that can be used to connect to this peer + """ + addresses: [String!]! + """ + The self-reported version of the client the peer is using + """ + clientVersion: String + """ + The last reported height of the peer + """ + blockHeight: U32 + """ + The last heartbeat from this peer in unix epoch time ms + """ + lastHeartbeatMs: U64! + """ + The internal fuel p2p reputation of this peer + """ + appScore: Float! +} + +type PoAConsensus { + """ + Gets the signature of the block produced by `PoA` consensus. + """ + signature: Signature! +} + +type Policies { + tip: U64 + witnessLimit: U64 + maturity: U32 + maxFee: U64 +} + +type PredicateParameters { + version: PredicateParametersVersion! + maxPredicateLength: U64! + maxPredicateDataLength: U64! + maxGasPerPredicate: U64! + maxMessageDataLength: U64! +} + +enum PredicateParametersVersion { + V1 +} + +type ProgramState { + returnType: ReturnType! + data: HexString! +} + +type Query { + """ + Read register value by index. + """ + register(id: ID!, register: U32!): U64! + """ + Read read a range of memory bytes. + """ + memory(id: ID!, start: U32!, size: U32!): String! + balance( + """ + address of the owner + """ + owner: Address!, + """ + asset_id of the coin + """ + assetId: AssetId! + ): Balance! + balances(filter: BalanceFilterInput!, first: Int, after: String, last: Int, before: String): BalanceConnection! + blob( + """ + ID of the Blob + """ + id: BlobId! + ): Blob + block( + """ + ID of the block + """ + id: BlockId, + """ + Height of the block + """ + height: U32 + ): Block + blocks(first: Int, after: String, last: Int, before: String): BlockConnection! + chain: ChainInfo! + transaction( + """ + The ID of the transaction + """ + id: TransactionId! + ): Transaction + transactions(first: Int, after: String, last: Int, before: String): TransactionConnection! + transactionsByOwner(owner: Address!, first: Int, after: String, last: Int, before: String): TransactionConnection! + """ + Estimate the predicate gas for the provided transaction + """ + estimatePredicates(tx: HexString!): Transaction! + """ + Returns all possible receipts for test purposes. + """ + allReceipts: [Receipt!]! + """ + Returns true when the GraphQL API is serving requests. + """ + health: Boolean! + """ + Gets the coin by `utxo_id`. + """ + coin( + """ + The ID of the coin + """ + utxoId: UtxoId! + ): Coin + """ + Gets all unspent coins of some `owner` maybe filtered with by `asset_id` per page. + """ + coins(filter: CoinFilterInput!, first: Int, after: String, last: Int, before: String): CoinConnection! + """ + For each `query_per_asset`, get some spendable coins(of asset specified by the query) owned by + `owner` that add up at least the query amount. The returned coins can be spent. + The number of coins is optimized to prevent dust accumulation. + + The query supports excluding and maximum the number of coins. + + Returns: + The list of spendable coins per asset from the query. The length of the result is + the same as the length of `query_per_asset`. The ordering of assets and `query_per_asset` + is the same. + """ + coinsToSpend( + """ + The `Address` of the coins owner. + """ + owner: Address!, + """ + The list of requested assets` coins with asset ids, `target` amount the user wants to reach, and the `max` number of coins in the selection. Several entries with the same asset id are not allowed. The result can't contain more coins than `max_inputs`. + """ + queryPerAsset: [SpendQueryElementInput!]!, + """ + The excluded coins from the selection. + """ + excludedIds: ExcludeInput + ): [[CoinType!]!]! + daCompressedBlock( + """ + Height of the block + """ + height: U32! + ): DaCompressedBlock + contract( + """ + ID of the Contract + """ + id: ContractId! + ): Contract + contractBalance(contract: ContractId!, asset: AssetId!): ContractBalance! + contractBalances(filter: ContractBalanceFilterInput!, first: Int, after: String, last: Int, before: String): ContractBalanceConnection! + nodeInfo: NodeInfo! + latestGasPrice: LatestGasPrice! + estimateGasPrice( + """ + Number of blocks into the future to estimate the gas price for + """ + blockHorizon: U32 + ): EstimateGasPrice! + message( + """ + The Nonce of the message + """ + nonce: Nonce! + ): Message + messages( + """ + address of the owner + """ + owner: Address, first: Int, after: String, last: Int, before: String + ): MessageConnection! + messageProof(transactionId: TransactionId!, nonce: Nonce!, commitBlockId: BlockId, commitBlockHeight: U32): MessageProof + messageStatus(nonce: Nonce!): MessageStatus! + relayedTransactionStatus( + """ + The id of the relayed tx + """ + id: RelayedTransactionId! + ): RelayedTransactionStatus + consensusParameters(version: Int!): ConsensusParameters! + stateTransitionBytecodeByVersion(version: Int!): StateTransitionBytecode + stateTransitionBytecodeByRoot(root: HexString!): StateTransitionBytecode! +} + +type Receipt { + id: ContractId + pc: U64 + is: U64 + to: ContractId + toAddress: Address + amount: U64 + assetId: AssetId + gas: U64 + param1: U64 + param2: U64 + val: U64 + ptr: U64 + digest: Bytes32 + reason: U64 + ra: U64 + rb: U64 + rc: U64 + rd: U64 + len: U64 + receiptType: ReceiptType! + result: U64 + gasUsed: U64 + data: HexString + sender: Address + recipient: Address + nonce: Nonce + """ + Set in the case of a Panic receipt to indicate a missing contract input id + """ + contractId: ContractId + subId: Bytes32 +} + +enum ReceiptType { + CALL + RETURN + RETURN_DATA + PANIC + REVERT + LOG + LOG_DATA + TRANSFER + TRANSFER_OUT + SCRIPT_RESULT + MESSAGE_OUT + MINT + BURN +} + +type RelayedTransactionFailed { + blockHeight: U32! + failure: String! +} + +scalar RelayedTransactionId + +union RelayedTransactionStatus = RelayedTransactionFailed + +enum ReturnType { + RETURN + RETURN_DATA + REVERT +} + +type RunResult { + state: RunState! + breakpoint: OutputBreakpoint + jsonReceipts: [String!]! +} + +enum RunState { + """ + All breakpoints have been processed, and the program has terminated + """ + COMPLETED + """ + Stopped on a breakpoint + """ + BREAKPOINT +} + +scalar Salt + +type ScriptParameters { + version: ScriptParametersVersion! + maxScriptLength: U64! + maxScriptDataLength: U64! +} + +enum ScriptParametersVersion { + V1 +} + +scalar Signature + +input SpendQueryElementInput { + """ + Identifier of the asset to spend. + """ + assetId: AssetId! + """ + Target amount for the query. + """ + amount: U64! + """ + The maximum number of currencies for selection. + """ + max: U32 +} + +type SqueezedOutStatus { + reason: String! +} + +type StateTransitionBytecode { + root: HexString! + bytecode: UploadedBytecode! +} + +type StateTransitionPurpose { + root: Bytes32! +} + + +type SubmittedStatus { + time: Tai64Timestamp! +} + +type Subscription { + """ + Returns a stream of status updates for the given transaction id. + If the current status is [`TransactionStatus::Success`], [`TransactionStatus::SqueezedOut`] + or [`TransactionStatus::Failed`] the stream will return that and end immediately. + If the current status is [`TransactionStatus::Submitted`] this will be returned + and the stream will wait for a future update. + + This stream will wait forever so it's advised to use within a timeout. + + It is possible for the stream to miss an update if it is polled slower + then the updates arrive. In such a case the stream will close without + a status. If this occurs the stream can simply be restarted to return + the latest status. + """ + statusChange( + """ + The ID of the transaction + """ + id: TransactionId! + ): TransactionStatus! + """ + Submits transaction to the `TxPool` and await either confirmation or failure. + """ + submitAndAwait(tx: HexString!): TransactionStatus! + """ + Submits the transaction to the `TxPool` and returns a stream of events. + Compared to the `submitAndAwait`, the stream also contains ` + SubmittedStatus` as an intermediate state. + """ + submitAndAwaitStatus(tx: HexString!): TransactionStatus! +} + +type SuccessStatus { + transactionId: TransactionId! + blockHeight: U32! + block: Block! + transaction: Transaction! + time: Tai64Timestamp! + programState: ProgramState + receipts: [Receipt!]! + totalGas: U64! + totalFee: U64! +} + +scalar Tai64Timestamp + +type Transaction { + id: TransactionId! + inputAssetIds: [AssetId!] + inputContracts: [ContractId!] + inputContract: InputContract + policies: Policies + scriptGasLimit: U64 + maturity: U32 + mintAmount: U64 + mintAssetId: AssetId + mintGasPrice: U64 + txPointer: TxPointer + isScript: Boolean! + isCreate: Boolean! + isMint: Boolean! + isUpgrade: Boolean! + isUpload: Boolean! + isBlob: Boolean! + inputs: [Input!] + outputs: [Output!]! + outputContract: ContractOutput + witnesses: [HexString!] + receiptsRoot: Bytes32 + status: TransactionStatus + script: HexString + scriptData: HexString + bytecodeWitnessIndex: U16 + blobId: BlobId + salt: Salt + storageSlots: [HexString!] + bytecodeRoot: Bytes32 + subsectionIndex: U16 + subsectionsNumber: U16 + proofSet: [Bytes32!] + upgradePurpose: UpgradePurpose + """ + Return the transaction bytes using canonical encoding + """ + rawPayload: HexString! +} + +type TransactionConnection { + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + """ + A list of edges. + """ + edges: [TransactionEdge!]! + """ + A list of nodes. + """ + nodes: [Transaction!]! +} + +""" +An edge in a connection. +""" +type TransactionEdge { + """ + The item at the end of the edge + """ + node: Transaction! + """ + A cursor for use in pagination + """ + cursor: String! +} + +scalar TransactionId + +union TransactionStatus = SubmittedStatus | SuccessStatus | SqueezedOutStatus | FailureStatus + +type TxParameters { + version: TxParametersVersion! + maxInputs: U16! + maxOutputs: U16! + maxWitnesses: U32! + maxGasPerTx: U64! + maxSize: U64! + maxBytecodeSubsections: U16! +} + +enum TxParametersVersion { + V1 +} + +scalar TxPointer + +scalar U16 + +scalar U32 + +scalar U64 + +union UpgradePurpose = ConsensusParametersPurpose | StateTransitionPurpose + +type UploadedBytecode { + """ + Combined bytecode of all uploaded subsections. + """ + bytecode: HexString! + """ + Number of uploaded subsections (if incomplete). + """ + uploadedSubsectionsNumber: Int + """ + Indicates if the bytecode upload is complete. + """ + completed: Boolean! +} + +scalar UtxoId + +type VariableOutput { + to: Address! + amount: U64! + assetId: AssetId! +} + +directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT +directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT +schema { + query: Query + mutation: Mutation + subscription: Subscription +} From f2c31029b78419dd186a1022b9ce53e87b757a03 Mon Sep 17 00:00:00 2001 From: hal3e Date: Mon, 11 Nov 2024 18:49:21 +0100 Subject: [PATCH 2/4] chore: version bump to `0.66.10` (#1545) --- Cargo.toml | 18 +++++++++--------- docs/src/connecting/short-lived.md | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f272a150e..5360aeb62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ readme = "README.md" license = "Apache-2.0" repository = "https://github.com/FuelLabs/fuels-rs" rust-version = "1.79.0" -version = "0.66.9" +version = "0.66.10" [workspace.dependencies] Inflector = "0.11.4" @@ -105,11 +105,11 @@ fuel-types = { version = "0.58.0" } fuel-vm = { version = "0.58.0" } # Workspace projects -fuels = { version = "0.66.9", path = "./packages/fuels", default-features = false } -fuels-accounts = { version = "0.66.9", path = "./packages/fuels-accounts", default-features = false } -fuels-code-gen = { version = "0.66.9", path = "./packages/fuels-code-gen", default-features = false } -fuels-core = { version = "0.66.9", path = "./packages/fuels-core", default-features = false } -fuels-macros = { version = "0.66.9", path = "./packages/fuels-macros", default-features = false } -fuels-programs = { version = "0.66.9", path = "./packages/fuels-programs", default-features = false } -fuels-test-helpers = { version = "0.66.9", path = "./packages/fuels-test-helpers", default-features = false } -versions-replacer = { version = "0.66.9", path = "./scripts/versions-replacer", default-features = false } +fuels = { version = "0.66.10", path = "./packages/fuels", default-features = false } +fuels-accounts = { version = "0.66.10", path = "./packages/fuels-accounts", default-features = false } +fuels-code-gen = { version = "0.66.10", path = "./packages/fuels-code-gen", default-features = false } +fuels-core = { version = "0.66.10", path = "./packages/fuels-core", default-features = false } +fuels-macros = { version = "0.66.10", path = "./packages/fuels-macros", default-features = false } +fuels-programs = { version = "0.66.10", path = "./packages/fuels-programs", default-features = false } +fuels-test-helpers = { version = "0.66.10", path = "./packages/fuels-test-helpers", default-features = false } +versions-replacer = { version = "0.66.10", path = "./scripts/versions-replacer", default-features = false } diff --git a/docs/src/connecting/short-lived.md b/docs/src/connecting/short-lived.md index 43450f91c..8d0257ea1 100644 --- a/docs/src/connecting/short-lived.md +++ b/docs/src/connecting/short-lived.md @@ -27,7 +27,7 @@ let wallet = launch_provider_and_get_wallet().await?; The `fuel-core-lib` feature allows us to run a `fuel-core` node without installing the `fuel-core` binary on the local machine. Using the `fuel-core-lib` feature flag entails downloading all the dependencies needed to run the fuel-core node. ```rust,ignore -fuels = { version = "0.66.9", features = ["fuel-core-lib"] } +fuels = { version = "0.66.10", features = ["fuel-core-lib"] } ``` ### RocksDB @@ -35,5 +35,5 @@ fuels = { version = "0.66.9", features = ["fuel-core-lib"] } The `rocksdb` is an additional feature that, when combined with `fuel-core-lib`, provides persistent storage capabilities while using `fuel-core` as a library. ```rust,ignore -fuels = { version = "0.66.9", features = ["rocksdb"] } +fuels = { version = "0.66.10", features = ["rocksdb"] } ``` From 1d06f47dedc42278f7b928f0945fb8f358be7b1c Mon Sep 17 00:00:00 2001 From: MujkicA <32431923+MujkicA@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:12:13 +0100 Subject: [PATCH 3/4] chore: update forc to `0.66.4` (#1539) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6bf6e2ab..52cad62d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ env: FUEL_CORE_PATCH_BRANCH: "" FUEL_CORE_PATCH_REVISION: "" RUST_VERSION: 1.79.0 - FORC_VERSION: 0.65.2 + FORC_VERSION: 0.66.4 FORC_PATCH_BRANCH: "" FORC_PATCH_REVISION: "" NEXTEST_HIDE_PROGRESS_BAR: "true" From 6d6639044207e29e489e4f7211b28e316b3e1089 Mon Sep 17 00:00:00 2001 From: AurelienFT <32803821+AurelienFT@users.noreply.github.com> Date: Wed, 11 Sep 2024 09:55:02 +0200 Subject: [PATCH 4/4] chore!: Move `get_asset_outputs_for_amount`, `get_asset_inputs_for_amount` and `adjust_for_fee` from `Account` to `ViewOnlyAccount` (#1498) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Release notes In this release, we: - Move `get_asset_outputs_for_amount` and `adjust_for_fee` from `Account` to `ViewOnlyAccount` # Summary This PR moves `get_asset_outputs_for_amount`, `get_asset_inputs_for_amount` and `adjust_for_fee` from `Account` to `ViewOnlyAccount` trait. It seem that these two methods doesn't require a full `Account` and so it give more flexibility in order to implement them in other structures such as `Wallet`. Now `Wallet` also implement these two methods. Before you were forced to build a `WalletUnlocked` even if you don't use the `secret_key`. # Breaking changes This contains an API breaking change as some public trait as been edited: # Breaking Changes The provider option flag `cacheUtxo` was renamed to `resourceCacheTTL` ```rust // before use fuels::acounts::Account; wallet.get_asset_outputs_for_amount(...); ``` ```rust // after use fuels::acounts::ViewOnlyAccount; wallet.get_asset_outputs_for_amount(...); ``` # Checklist - [x] All **changes** are **covered** by **tests** (or not applicable) - [x] All **changes** are **documented** (or not applicable) - [x] I **reviewed** the **entire PR** myself (preferably, on GH UI) - [x] I **described** all **Breaking Changes** (or there's none) --------- Co-authored-by: hal3e Co-authored-by: Rodrigo Araújo Co-authored-by: MujkicA --- .../transaction-builders.md | 2 +- examples/cookbook/src/lib.rs | 2 +- packages/fuels-accounts/src/account.rs | 26 +++++++------- .../src/impersonated_account.rs | 8 ++--- packages/fuels-accounts/src/predicate.rs | 8 ++--- packages/fuels-accounts/src/wallet.rs | 34 ++++++++++++------- 6 files changed, 42 insertions(+), 38 deletions(-) diff --git a/docs/src/custom-transactions/transaction-builders.md b/docs/src/custom-transactions/transaction-builders.md index 629f96b16..03cfbbe82 100644 --- a/docs/src/custom-transactions/transaction-builders.md +++ b/docs/src/custom-transactions/transaction-builders.md @@ -60,7 +60,7 @@ As we have used coins that require a signature, we have to add the signer to the > **Note** The signature is not created until the transaction is finalized with `build(&provider)` -We need to do one more thing before we stop thinking about transaction inputs. Executing the transaction also incurs a fee that is paid with the base asset. Our base asset inputs need to be large enough so that the total amount covers the transaction fee and any other operations we are doing. The `Account` trait lets us use `adjust_for_fee()` for adjusting the transaction inputs if needed to cover the fee. The second argument to `adjust_for_fee()` is the total amount of the base asset that we expect our transaction to spend regardless of fees. In our case, this is the **ask_amount** we are transferring to the predicate. +We need to do one more thing before we stop thinking about transaction inputs. Executing the transaction also incurs a fee that is paid with the base asset. Our base asset inputs need to be large enough so that the total amount covers the transaction fee and any other operations we are doing. The `ViewOnlyAccount` trait lets us use `adjust_for_fee()` for adjusting the transaction inputs if needed to cover the fee. The second argument to `adjust_for_fee()` is the total amount of the base asset that we expect our transaction to spend regardless of fees. In our case, this is the **ask_amount** we are transferring to the predicate. ```rust,ignore {{#include ../../../examples/cookbook/src/lib.rs:custom_tx_adjust}} diff --git a/examples/cookbook/src/lib.rs b/examples/cookbook/src/lib.rs index 88c8a0bae..7814432c4 100644 --- a/examples/cookbook/src/lib.rs +++ b/examples/cookbook/src/lib.rs @@ -3,7 +3,7 @@ mod tests { use std::{str::FromStr, time::Duration}; use fuels::{ - accounts::{predicate::Predicate, wallet::WalletUnlocked, Account, ViewOnlyAccount}, + accounts::{predicate::Predicate, wallet::WalletUnlocked, ViewOnlyAccount}, prelude::Result, test_helpers::{setup_single_asset_coins, setup_test_provider}, types::{ diff --git a/packages/fuels-accounts/src/account.rs b/packages/fuels-accounts/src/account.rs index 7801e4973..dbc46dab9 100644 --- a/packages/fuels-accounts/src/account.rs +++ b/packages/fuels-accounts/src/account.rs @@ -92,20 +92,6 @@ pub trait ViewOnlyAccount: std::fmt::Debug + Send + Sync + Clone { self.try_provider()?.get_spendable_resources(filter).await } -} - -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] -pub trait Account: ViewOnlyAccount { - /// Returns a vector consisting of `Input::Coin`s and `Input::Message`s for the given - /// asset ID and amount. The `witness_index` is the position of the witness (signature) - /// in the transaction's list of witnesses. In the validation process, the node will - /// use the witness at this index to validate the coins returned by this method. - async fn get_asset_inputs_for_amount( - &self, - asset_id: AssetId, - amount: u64, - excluded_coins: Option>, - ) -> Result>; /// Returns a vector containing the output coin and change output given an asset and amount fn get_asset_outputs_for_amount( @@ -122,6 +108,15 @@ pub trait Account: ViewOnlyAccount { ] } + /// Returns a vector consisting of `Input::Coin`s and `Input::Message`s for the given + /// asset ID and amount. + async fn get_asset_inputs_for_amount( + &self, + asset_id: AssetId, + amount: u64, + excluded_coins: Option>, + ) -> Result>; + /// Add base asset inputs to the transaction to cover the estimated fee. /// Requires contract inputs to be at the start of the transactions inputs vec /// so that their indexes are retained @@ -155,7 +150,10 @@ pub trait Account: ViewOnlyAccount { Ok(()) } +} +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +pub trait Account: ViewOnlyAccount { // Add signatures to the builder if the underlying account is a wallet fn add_witnesses(&self, _tb: &mut Tb) -> Result<()> { Ok(()) diff --git a/packages/fuels-accounts/src/impersonated_account.rs b/packages/fuels-accounts/src/impersonated_account.rs index 77e4f1994..10f3759df 100644 --- a/packages/fuels-accounts/src/impersonated_account.rs +++ b/packages/fuels-accounts/src/impersonated_account.rs @@ -29,6 +29,7 @@ impl ImpersonatedAccount { } } +#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)] impl ViewOnlyAccount for ImpersonatedAccount { fn address(&self) -> &Bech32Address { self.address() @@ -37,12 +38,7 @@ impl ViewOnlyAccount for ImpersonatedAccount { fn try_provider(&self) -> Result<&Provider> { self.provider.as_ref().ok_or_else(try_provider_error) } -} -#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)] -impl Account for ImpersonatedAccount { - /// Returns a vector consisting of `Input::Coin`s and `Input::Message`s for the given - /// asset ID and amount. async fn get_asset_inputs_for_amount( &self, asset_id: AssetId, @@ -56,7 +52,9 @@ impl Account for ImpersonatedAccount { .map(Input::resource_signed) .collect::>()) } +} +impl Account for ImpersonatedAccount { fn add_witnesses(&self, tb: &mut Tb) -> Result<()> { tb.add_signer(self.clone())?; diff --git a/packages/fuels-accounts/src/predicate.rs b/packages/fuels-accounts/src/predicate.rs index c623d053a..6fc1262ef 100644 --- a/packages/fuels-accounts/src/predicate.rs +++ b/packages/fuels-accounts/src/predicate.rs @@ -101,6 +101,7 @@ impl Predicate { } #[cfg(feature = "std")] +#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)] impl ViewOnlyAccount for Predicate { fn address(&self) -> &Bech32Address { self.address() @@ -109,11 +110,7 @@ impl ViewOnlyAccount for Predicate { fn try_provider(&self) -> Result<&Provider> { self.provider.as_ref().ok_or_else(try_provider_error) } -} -#[cfg(feature = "std")] -#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)] -impl Account for Predicate { async fn get_asset_inputs_for_amount( &self, asset_id: AssetId, @@ -130,3 +127,6 @@ impl Account for Predicate { .collect::>()) } } + +#[cfg(feature = "std")] +impl Account for Predicate {} diff --git a/packages/fuels-accounts/src/wallet.rs b/packages/fuels-accounts/src/wallet.rs index fe124f58e..45fec01d2 100644 --- a/packages/fuels-accounts/src/wallet.rs +++ b/packages/fuels-accounts/src/wallet.rs @@ -78,6 +78,7 @@ impl Wallet { } } +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl ViewOnlyAccount for Wallet { fn address(&self) -> &Bech32Address { self.address() @@ -86,6 +87,20 @@ impl ViewOnlyAccount for Wallet { fn try_provider(&self) -> Result<&Provider> { self.provider.as_ref().ok_or_else(try_provider_error) } + + async fn get_asset_inputs_for_amount( + &self, + asset_id: AssetId, + amount: u64, + excluded_coins: Option>, + ) -> Result> { + Ok(self + .get_spendable_resources(asset_id, amount, excluded_coins) + .await? + .into_iter() + .map(Input::resource_signed) + .collect::>()) + } } impl WalletUnlocked { @@ -190,6 +205,7 @@ impl WalletUnlocked { } } +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl ViewOnlyAccount for WalletUnlocked { fn address(&self) -> &Bech32Address { self.wallet.address() @@ -198,28 +214,20 @@ impl ViewOnlyAccount for WalletUnlocked { fn try_provider(&self) -> Result<&Provider> { self.provider.as_ref().ok_or_else(try_provider_error) } -} -#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)] -impl Account for WalletUnlocked { - /// Returns a vector consisting of `Input::Coin`s and `Input::Message`s for the given - /// asset ID and amount. The `witness_index` is the position of the witness (signature) - /// in the transaction's list of witnesses. In the validation process, the node will - /// use the witness at this index to validate the coins returned by this method. async fn get_asset_inputs_for_amount( &self, asset_id: AssetId, amount: u64, excluded_coins: Option>, ) -> Result> { - Ok(self - .get_spendable_resources(asset_id, amount, excluded_coins) - .await? - .into_iter() - .map(Input::resource_signed) - .collect::>()) + self.wallet + .get_asset_inputs_for_amount(asset_id, amount, excluded_coins) + .await } +} +impl Account for WalletUnlocked { fn add_witnesses(&self, tb: &mut Tb) -> Result<()> { tb.add_signer(self.clone())?;