diff --git a/crates/sui-graphql-rpc/schema/current_progress_schema.graphql b/crates/sui-graphql-rpc/schema/current_progress_schema.graphql index bd7e082a42570..6b9f24871f86d 100644 --- a/crates/sui-graphql-rpc/schema/current_progress_schema.graphql +++ b/crates/sui-graphql-rpc/schema/current_progress_schema.graphql @@ -206,6 +206,9 @@ type BalanceEdge { scalar Base64 +""" +String representation of an arbitrary width, possibly signed integer. +""" scalar BigInt @@ -332,6 +335,9 @@ type CheckpointEdge { cursor: String! } +""" +Filter either by the digest, or the sequence number, or neither, to get the latest checkpoint. +""" input CheckpointId { digest: String sequenceNumber: Int @@ -434,6 +440,9 @@ type ConsensusCommitPrologueTransaction { consensusCommitDigest: String } +""" +ISO-8601 Date and Time: RFC3339 in UTC with format: YYYY-MM-DDTHH:MM:SS.mmmZ +""" scalar DateTime type DynamicField { @@ -685,18 +694,14 @@ input EventFilter { sender: SuiAddress transactionDigest: String """ - Events emitted by a particular package. - An event is emitted by a particular package - if some function in the package is called - by a PTB and emits an event. + Events emitted by a particular package. An event is emitted by a particular package if some + function in the package is called by a PTB and emits an event. """ emittingPackage: SuiAddress """ - Events emitted by a particular Move module. - An event is emitted by a particular module - if some function in the module is called - by a PTB and emits an event. - Requires `emitting_package` to be set. + Events emitted by a particular Move module. An event is emitted by a particular module if + some function in the module is called by a PTB and emits an event. Requires + `emitting_package` to be set. """ emittingModule: String eventPackage: SuiAddress @@ -1480,14 +1485,26 @@ type ObjectEdge { input ObjectFilter { """ - This field is used to specify the type of objects that should be included - in the query results. Generic types can be queried by either the generic - type name, e.g. `0x2::coin::Coin`, or by the full type name, such as - `0x2::coin::Coin<0x2::sui::SUI>`. + This field is used to specify the type of objects that should be include in the query + results. + + Type can be filtered by their package, package::module, or their fuly qualified type name. + + Generic types can be queried by either the generic type name, e.g. `0x2::coin::Coin`, or by + the full type name, such as `0x2::coin::Coin<0x2::sui::SUI>`. """ type: String + """ + Filter for live objects by their current owners. + """ owner: SuiAddress + """ + Filter for live objects by their IDs. + """ objectIds: [SuiAddress!] + """ + Filter for live or potentially historical objects by their ID and version. + """ objectKeys: [ObjectKey!] } @@ -1524,11 +1541,11 @@ type OpenMoveType { """ Structured representation of the type signature. """ - signature: OpenMoveTypeSignature + signature: OpenMoveTypeSignature! """ Flat representation of the type signature, as a displayable string. """ - repr: String + repr: String! } """ @@ -1772,8 +1789,18 @@ type Query { owner(address: SuiAddress!): ObjectOwner object(address: SuiAddress!, version: Int): Object address(address: SuiAddress!): Address + """ + Fetch epoch information by ID (defaults to the latest epoch). + """ epoch(id: Int): Epoch + """ + Fetch checkpoint information by sequence number or digest (defaults to the latest available + checkpoint). + """ checkpoint(id: CheckpointId): Checkpoint + """ + Fetch a transaction block by its transaction digest. + """ transactionBlock(digest: String!): TransactionBlock """ The coin objects that exist in the network. @@ -1786,6 +1813,10 @@ type Query { transactionBlockConnection(first: Int, after: String, last: Int, before: String, filter: TransactionBlockFilter): TransactionBlockConnection eventConnection(first: Int, after: String, last: Int, before: String, filter: EventFilter): EventConnection objectConnection(first: Int, after: String, last: Int, before: String, filter: ObjectFilter): ObjectConnection + """ + Fetch the protocl config by protocol version (defaults to the latest protocol + version known to the GraphQL) + """ protocolConfig(protocolVersion: Int): ProtocolConfigs! """ Resolves the owner address of the provided domain name @@ -1890,15 +1921,15 @@ type ServiceConfig { """ Default number of elements allowed on a single page of a connection. """ - defaultPageSize: BigInt! + defaultPageSize: Int! """ Maximum number of elements allowed on a single page of a connection. """ - maxPageSize: BigInt! + maxPageSize: Int! """ Maximum time in milliseconds that will be spent to serve one request. """ - requestTimeoutMs: BigInt! + requestTimeoutMs: Int! """ Maximum length of a query payload string. """ @@ -2065,6 +2096,9 @@ type StorageFund { } +""" +String containing 32B hex-encoded address, with a leading "0x". Leading zeroes can be omitted on input but will always appear in outputs (SuiAddress in output is guaranteed to be 66 characters long). +""" scalar SuiAddress """ diff --git a/crates/sui-graphql-rpc/schema/draft_target_schema.graphql b/crates/sui-graphql-rpc/schema/draft_target_schema.graphql index 675118496bb05..103ac7cb43ae7 100644 --- a/crates/sui-graphql-rpc/schema/draft_target_schema.graphql +++ b/crates/sui-graphql-rpc/schema/draft_target_schema.graphql @@ -50,72 +50,69 @@ type Query { # checks that prevent access to objects that are owned by # addresses other than the sender, and calling non-public, # non-entry functions. Defaults to false. - # - # `epoch` the epoch to simulate executing the transaction in. - # Defaults to the current epoch. dryRunTransactionBlock( txBytes: Base64!, txMeta: TransactionMetadata, skipChecks: Boolean, - epoch: Int ): DryRunResult owner(address: SuiAddress!): Owner object(address: SuiAddress!, version: Int): Object address(address: SuiAddress!): Address - # `epochId` defaults to the latest epoch. - epoch(epochId: Int): Epoch + # Fetch epoch information by ID (defaults to the latest epoch). + epoch(id: Int): Epoch # `protocolVersion` defaults to the latest protocol version. protocolConfig(protocolVersion: Int): ProtocolConfigs - # If no `id` is provided, fetch the latest available checkpoint. - checkpoint(id: CheckpointID): Checkpoint + # Fetch checkpoint information by sequence number or digest + # (defaults to the latest available checkpoint). + checkpoint(id: CheckpointId): Checkpoint - # Find a transaction block by its transaction digest + # Fetch a transaction block by its transaction digest transactionBlock(digest: String!): TransactionBlock coinMetadata(coinType: String!): CoinMetadata - checkpointConnection( + checkpoints( first: Int, after: String, last: Int, before: String, - ): CheckpointConnection + ): CheckpointConnection! - coinConnection( + coins( first: Int, after: String, last: Int, before: String, type: String, - ): CheckpointConnection + ): CoinConnection! - transactionBlockConnection( + transactionBlocks( first: Int, after: String, last: Int, before: String, filter: TransactionBlockFilter, - ): TransactionBlockConnection + ): TransactionBlockConnection! - eventConnection( + events( first: Int, after: String, last: Int, before: String, filter: EventFilter, - ): EventConnection + ): EventConnection! - objectConnection( + objects( first: Int, after: String, last: Int, before: String, filter: ObjectFilter, - ): ObjectConnection + ): ObjectConnection! resolveNameServiceAddress(name: String!): Address @@ -123,12 +120,12 @@ type Query { networkMetrics: NetworkMetrics moveCallMetrics: MoveCallMetrics - allEpochAddressMetricsConnection( + allEpochAddressMetrics( first: Int, after: String, last: Int, before: String, - ): AddressMetricsConnection + ): AddressMetricsConnection! } # NB. Add after MVP has stabilised. @@ -141,14 +138,14 @@ type Query { # e.g. When subscription `subscribe { events(filter: F) }` pushes # cursor `E`. Then # -# query { eventsConnection(before: E, filter: F) } +# query { events(before: E, filter: F) } # # Will start paginating events up to the new data (multiple calls may # be required if there are multiple pages of information between the # start and the latest). If the client has already processed some # prefix, up to cursor `P`, then they can resume with: # -# query { eventsConnection(after: P, before: E, filter: F) } +# query { events(after: P, before: E, filter: F) } # # The API for transactions is similar. type Subscription { @@ -173,7 +170,10 @@ type Mutation { ): ExecutionResult } -# String containing 32B hex-encoded address +# String containing 32B hex-encoded address, with a leading "0x". +# Leading zeroes can be omitted on input but will always appear in +# outputs (SuiAddress in output is guaranteed to be 66 characters +# long). scalar SuiAddress # String representation of an arbitrary width, possibly signed integer @@ -248,12 +248,14 @@ scalar MoveTypeLayout # | "u8" | "u16" | ... | "u256" # | { vector: OpenMoveTypeSignatureBody } # | { -# package: string, -# module: string, -# type: string, -# typeParameters: [OpenMoveTypeSignatureBody]? +# struct: { +# package: string, +# module: string, +# type: string, +# typeParameters: [OpenMoveTypeSignatureBody]? +# } # } -# | { TypeParameter: number } +# | { typeParameter: number } scalar OpenMoveTypeSignature # The extra data required to turn a `TransactionKind` into a @@ -261,24 +263,43 @@ scalar OpenMoveTypeSignature input TransactionMetadata { sender: SuiAddress gasPrice: BigInt - gasObjects: [SuiAddress!] + gasBudget: BigInt + gasObjects: [ObjectRef!] +} + +# A reference to a particular version of an object. +input ObjectRef { + address: SuiAddress! + version: Int! + digest: String! } # Filter either by the digest, or the sequence number, or neither, to # get the latest checkpoint. -input CheckpointID { +input CheckpointId { digest: String sequenceNumber: Int } input ObjectFilter { - # Cascading (type requires module requires package) - package: SuiAddress - module: String + # This field is used to specify the type of objects that should be + # include in the query results. + # + # Type can be filtered by their package, package::module, or their + # fuly qualified type name. + # + # Generic types can be queried by either the generic type name, e.g. + # `0x2::coin::Coin`, or by the full type name, such as + # `0x2::coin::Coin<0x2::sui::SUI>`. type: String + # Filter for live objects by their current owners. owner: SuiAddress + + # Filter for live objects by their IDs. objectIds: [SuiAddress!] + + # Filter for live or potentially historical objects by their ID and version. objectKeys: [ObjectKey!] # Enhancement (post-MVP), compound filters. Compound filters are @@ -300,13 +321,21 @@ input EventFilter { afterCheckpoint: Int beforeCheckpoint: Int - # Cascading (module requires package) - emittingPackage: SuiAddress + # Events emitted by a particular module. An event is emitted by a + # particular module if some function in the module is called by a + # PTB and emits an event. + # + # Modules can be filtered by their package, or package::module. emittingModule: String - # Cascading (type requires module requires package) - eventPackage: SuiAddress - eventModule: String + # This field is used to specify the type of event emitted. + # + # Type can be filtered by their package, package::module, or their + # fuly qualified type name. + # + # Generic types can be queried by either the generic type name, e.g. + # `0x2::coin::Coin`, or by the full type name, such as + # `0x2::coin::Coin<0x2::sui::SUI>`. eventType: String # Enhancement (post-MVP), requires compound filters to be useful. @@ -321,9 +350,8 @@ input EventFilter { } input TransactionBlockFilter { - # Cascading (function requires module requires package) - package: SuiAddress - module: String + # Filter by the function called. Limited to an individual package, + # package::module, or package::module::function. function: String kind: TransactionBlockKindInput @@ -353,14 +381,24 @@ input TransactionBlockFilter { } input DynamicFieldFilter { - # Cascading (type requires module requires package) - namePackage: SuiAddress - nameModule: String + # Filter the type of dynamic field name. + # + # Type can be filtered by their package, package::module, or their + # fuly qualified type name. + # + # Generic types can be queried by either the generic type name, e.g. + # `0x2::coin::Coin`, or by the full type name, such as + # `0x2::coin::Coin<0x2::sui::SUI>`. nameType: String - # Cascading (type requires module requires package) - valuePackage: SuiAddress - valueModule: String + # Filter the type of dynamic field value. + # + # Type can be filtered by their package, package::module, or their + # fuly qualified type name. + # + # Generic types can be queried by either the generic type name, e.g. + # `0x2::coin::Coin`, or by the full type name, such as + # `0x2::coin::Coin<0x2::sui::SUI>`. valueType: String } @@ -373,8 +411,12 @@ type ServiceConfig { enabledFeatures: [Feature!] isEnabled(feature: Feature!): Boolean! - maxQueryDepth: Int - maxQueryNodes: Int + maxQueryDepth: Int! + maxQueryNodes: Int! + defaultPageSize: Int! + maxPageSize: Int! + requestTimeoutMs: Int! + maxQueryPayloadSize: Int! } enum Feature { @@ -389,63 +431,85 @@ enum Feature { interface IOwner { address: SuiAddress! - objectConnection( + objects( first: Int, after: String, last: Int, before: String, # Enhancement (post-MVP) relies on compound filters. filter: ObjectFilter, - ): MoveObjectConnection + ): MoveObjectConnection! balance(type: String!): Balance - balanceConnection( + balances( first: Int, after: String, last: Int, before: String, - ): BalanceConnection + ): BalanceConnection! # `type` defaults to `0x2::sui::SUI`. - coinConnection( + coins( first: Int, after: String, last: Int, before: String, type: String, - ): CoinConnection + ): CoinConnection! - stakedSuiConnection( + stakedSuis( first: Int, after: String, last: Int, before: String, - ): StakeConnection + ): StakedSuiConnection! dynamicField(dynamicFieldName: DynamicFieldName!): DynamicField - dynamicFieldConnection( + dynamicObjectField(dynamicFieldName: DynamicFieldName!): DynamicField + dynamicFields( first: Int, after: String, last: Int, before: String, # Enhancement (post-MVP) to filter dynamic fields by type. filter: DynamicFieldFilter, - ): DynamicFieldConnection + ): DynamicFieldConnection! defaultNameServiceName: String - nameServiceNameConnection( + nameServiceNames( first: Int, after: String, last: Int, before: String, - ): NameServiceNameConnection + ): NameServiceNameConnection! +} + +union ObjectOwner = Immutable | Shared | Parent | AddressOwner + +type Immutable { + # Dummy field + _: Boolean +} + +type Shared { + initialSharedVersion: Int! +} + +type Parent { + # Child objects are an implementation-detail of dynamic fields. Only + # another object can be a parent of a child object (not an address). + parent: Object +} + +type AddressOwner { + # The address that owns an object could be an Address, or an Object. + owner: Owner } interface IObject { version: Int! digest: String! - owner: Owner - kind: ObjectKind + owner: ObjectOwner previousTransactionBlock: TransactionBlock storageRebate: BigInt @@ -453,21 +517,20 @@ interface IObject { display: [DisplayEntry!] # Transaction Blocks that sent objects to this object - receivedTransactionBlockConnection( + receivedTransactionBlocks( first: Int, after: String, last: Int, before: String, # Enhancement (post-MVP) relies on compound filters. filter: TransactionBlockFilter, - ): TransactionBlockConnection + ): TransactionBlockConnection! bcs: Base64 } interface IMoveObject { contents: MoveValue - hasPublicTransfer: Boolean } # Returned by Object.owner, where we can't disambiguate between @@ -478,7 +541,7 @@ type Owner implements IOwner { } type Address implements IOwner { - transactionBlockConnection( + transactionBlocks( first: Int, after: String, last: Int, @@ -486,7 +549,7 @@ type Address implements IOwner { relation: AddressTransactionBlockRelationship, # Enhancement (post-MVP) relies on compound filters. filter: TransactionBlockFilter, - ): TransactionBlockConnection + ): TransactionBlockConnection! } enum AddressTransactionBlockRelationship { @@ -496,13 +559,6 @@ enum AddressTransactionBlockRelationship { PAID # Transactions that were paid for by this address } -enum ObjectKind { - OWNED - CHILD - SHARED - IMMUTABLE -} - type Object implements IOwner & IObject { asMoveObject: MoveObject asMovePackage: MovePackage @@ -518,7 +574,7 @@ type Epoch { protocolConfigs: ProtocolConfigs referenceGasPrice: BigInt - startTimestamp: DateTime + startTimestamp: DateTime! endTimestamp: DateTime totalCheckpoints: BigInt @@ -533,21 +589,21 @@ type Epoch { # TODO: Identify non-duplicate fields in `EndOfEpochInfo` systemState: SystemState - checkpointConnection( + checkpoints( first: Int, after: String, last: Int, before: String, - ): CheckpointConnection + ): CheckpointConnection! - transactionBlockConnection( + transactionBlocks( first: Int, after: String, last: Int, before: String, # Enhancement (post-MVP) relies on compound filters. filter: TransactionBlockFilter, - ): TransactionBlockConnection + ): TransactionBlockConnection! } type SystemState { @@ -602,7 +658,12 @@ type StakeSubsidy { type ValidatorSet { totalStake: BigInt - activeValidators: [Validator] + activeValidators( + first: Int, + after: String, + last: Int, + before: String + ): ValidatorConnection! # Indices into `activeValidators` pendingRemovals: [Int] @@ -658,7 +719,7 @@ type Validator { atRisk: Int # The other validators this validator has reported - reportRecords: [SuiAddress] + reportRecords: [SuiAddress!] apy: Int } @@ -689,7 +750,7 @@ type Checkpoint { digest: String! sequenceNumber: Int! - timestamp: DateTime + timestamp: DateTime! validatorSignature: Base64 # Commitments @@ -701,14 +762,14 @@ type Checkpoint { epoch: Epoch - transactionBlockConnection( + transactionBlocks( first: Int, after: String, last: Int, before: String, # Enhancement (post-MVP) relies on compound filters. filter: TransactionBlockFilter, - ): TransactionBlockConnection + ): TransactionBlockConnection! # NB. Will be moved into a private, explorer-specific extension. addressMetrics: AddressMetrics @@ -717,7 +778,7 @@ type Checkpoint { type TransactionBlock { digest: String! - senders: [Address] + sender: Address gasInput: GasInput kind: TransactionBlockKind signatures: [Base64!] @@ -743,45 +804,87 @@ union TransactionBlockKind = | EndOfEpochTransaction type ConsensusCommitPrologueTransaction { - epoch: Epoch - # TODO: This is the "leader round" -- does this line up with - # checkpoints? In which case, it may suffice to have a `Checkpoint` - # here. - round: Int - timestamp: DateTime + epoch: Epoch! + round: Int! + commitTimestamp: DateTime! + consensusCommitDigest: String } type GenesisTransaction { - objects: [SuiAddress] + objects( + first: Int, + after: String, + last: Int, + before: String, + ): ObjectConnection! } type ChangeEpochTransaction { epoch: Epoch - timestamp: DateTime + protocolVersion: Int! + startTimestamp: DateTime! - storageCharge: BigInt - computationCharge: BigInt - storageRebate: BigInt + storageCharge: BigInt! + computationCharge: BigInt! + storageRebate: BigInt! + nonRefundableStorageFee: BigInt! + + systemPackages( + first: Int, + after: String, + last: Int, + before: String, + ): MovePackageConnection! } type ProgrammableTransactionBlock { - inputs: [TransactionInput] - transactions: [ProgrammableTransaction] + inputs( + first: Int, + after: String, + last: Int, + before: String, + ): TransactionInputConnection! + + transactions( + first: Int, + after: String, + last: Int, + before: String, + ): ProgrammableTransactionConnection! } -union TransactionInput = MovePackage | MoveObject | SharedInput +union TransactionInput = OwnedOrImmutable | SharedInput | Receiving | Pure + +type OwnedOrImmutable { + address: SuiAddress! + version: Int! + digest: String! + object: Object +} type SharedInput { - id: SuiAddress - initialSharedVersion: Int - mutable: Boolean + address: SuiAddress! + initialSharedVersion: Int! + mutable: Boolean! +} + +type Receiving { + address: SuiAddress! + version: Int! + digest: String! + object: Object } +type Pure { + bytes: Base64! +} + + union TransactionArgument = GasCoin | Input | Result -type GasCoin -type Input { ix: Int } -type Result { cmd: Int, ix: Int } +type GasCoin { _: Boolean } +type Input { ix: Int! } +type Result { cmd: Int!, ix: Int } union ProgrammableTransaction = MoveCallTransaction @@ -793,39 +896,44 @@ union ProgrammableTransaction = | MakeMoveVecTransaction type MoveCallTransaction { + package: SuiAddress! + module: String! + functionName: String! function: MoveFunction - typeArguments: [MoveType] - arguments: [TransactionArgument] + typeArguments: [MoveType!]! + arguments: [TransactionArgument!]! } type TransferObjectsTransaction { - objects: [TransactionArgument] - address: TransactionArgument + objects: [TransactionArgument!]! + address: TransactionArgument! } -type SplitCoinTransaction { - coin: TransactionArgument - amounts: [TransactionArgument] +type SplitCoinsTransaction { + coin: TransactionArgument! + amounts: [TransactionArgument!]! } type MergeCoinsTransaction { - coin: TransactionArgument - coins: [TransactionArgument] + coin: TransactionArgument! + coins: [TransactionArgument!]! } type PublishTransaction { - dependencies: [MovePackage] + modules: [Base64!]! + dependencies: [SuiAddress!]! } type UpgradeTransaction { - dependencies: [MovePackage] - currentPackage: MovePackage - upgradeTicket: TransactionArgument + modules: [Base64!]! + dependencies: [SuiAddress!]! + currentPackage: SuiAddress! + upgradeTicket: TransactionArgument! } type MakeMoveVecTransaction { type: MoveType - elements: [TransactionArgument] + elements: [TransactionArgument!]! } type TransactionBlockEffects { @@ -833,25 +941,49 @@ type TransactionBlockEffects { status: ExecutionStatus errors: String - dependencies: [TransactionBlock!] + dependencies( + first: Int, + after: String, + last: Int, + before: String, + ): TransactionBlockConnection! lamportVersion: Int gasEffects: GasEffects - objectReads: [Object!] - objectChanges: [ObjectChange!] - balanceChanges: [BalanceChange!] + + unchangedSharedObjects( + first: Int, + after: String, + last: Int, + before: String, + ): MoveObjectConnection! + + objectChanges( + first: Int, + after: String, + last: Int, + before: String, + ): ObjectChangeConnection! + + balanceChanges( + first: Int, + after: String, + last: Int, + before: String, + ): BalanceChangeConnection! + timestamp: DateTime epoch: Epoch checkpoint: Checkpoint - eventConnection( + events( first: Int, after: String, last: Int, before: String, # Extension (post-MVP) relies on compound filters filter: EventFilter, - ): EventConnection + ): EventConnection! bcs: Base64 } @@ -863,7 +995,12 @@ enum ExecutionStatus { type GasInput { gasSponsor: Address - gasPayment: [Object!] + gasPayment( + first: Int, + after: String, + last: Int, + before: String, + ): ObjectConnection! gasPrice: BigInt gasBudget: BigInt @@ -901,7 +1038,7 @@ type Event { # Module that the event was emitted by sendingModule: MoveModule - senders: [Address] + sender: Address timestamp: DateTime type: MoveType! @@ -921,7 +1058,7 @@ type Coin implements IOwner & IObject { } type StakedSui implements IOwner & IObject { - status: StakeStatus + status: StakeStatus! requestEpoch: Epoch activeEpoch: Epoch principal: BigInt @@ -941,7 +1078,7 @@ type CoinMetadata implements IOwner & IObject { name: String symbol: String description: String - iconURL: String + iconUrl: String supply: BigInt } @@ -965,15 +1102,15 @@ type MoveObject implements IOwner & IObject & IMoveObject { type MovePackage implements IOwner & IObject { module(name: String!): MoveModule - moduleConnection( + modules( first: Int, after: String, last: Int, before: String, - ): MoveModuleConnection + ): MoveModuleConnection! linkage: [Linkage!] - origins: [TypeOrigin!] + typeOrigins: [TypeOrigin!] moduleBcs: Base64 } @@ -986,8 +1123,8 @@ type Linkage { type TypeOrigin { module: String! - name: String! - package: SuiAddress! + struct: String! + definingId: SuiAddress! } enum MoveAbility { @@ -1004,12 +1141,12 @@ enum MoveVisibility { } type MoveStructTypeParameter { - constraints: [MoveAbility] - isPhantom: Boolean + constraints: [MoveAbility!]! + isPhantom: Boolean! } type MoveFunctionTypeParameter { - constraints: [MoveAbility] + constraints: [MoveAbility!]! } type MoveModule { @@ -1018,28 +1155,28 @@ type MoveModule { fileFormatVersion: Int! - friendConnection( + friends( first: Int, after: String, last: Int, before: String - ): MoveModuleConnection + ): MoveModuleConnection! struct(name: String!): MoveStruct - structConnection( + structs( first: Int, after: String, last: Int, before: String, - ): MoveStructConnection + ): MoveStructConnection! function(name: String!): MoveFunction - functionConnection( + functions( first: Int, after: String, last: Int, before: String, - ): MoveFunctionConnection + ): MoveFunctionConnection! bytes: Base64 disassembly: String @@ -1048,13 +1185,13 @@ type MoveModule { type MoveStruct { module: MoveModule! name: String! - abilities: [MoveAbility] - typeParameters: [MoveStructTypeParameter] - fields: [MoveField] + abilities: [MoveAbility!] + typeParameters: [MoveStructTypeParameter!] + fields: [MoveField!] } type MoveField { - name: String + name: String! type: OpenMoveType } @@ -1065,27 +1202,27 @@ type MoveFunction { visibility: MoveVisibility isEntry: Boolean - typeParameters: [MoveFunctionTypeParameter] - parameters: [OpenMoveType] - return: [OpenMoveType] + typeParameters: [MoveFunctionTypeParameter!] + parameters: [OpenMoveType!] + return: [OpenMoveType!] } type MoveValue { type: MoveType! - data: MoveData - json: JSON + data: MoveData! + json: JSON! - bcs: Base64 + bcs: Base64! } # Represents concrete types (no type parameters, no references) type MoveType { # Flat representation of the type signature, as a displayable string. - repr: String + repr: String! # Structured representation of the type signature. - signature: MoveTypeSignature + signature: MoveTypeSignature! # Structured representation of the "shape" of values that match this type. - layout: MoveTypeLayout + layout: MoveTypeLayout! } # Represents types that could contain references or free type @@ -1093,9 +1230,9 @@ type MoveType { # in structs. type OpenMoveType { # Flat representation of the type signature, as a displayable string. - repr: String + repr: String! # Structured representation of the type signature. - signature: OpenMoveTypeSignature + signature: OpenMoveTypeSignature! } # Metrics (omitted for brevity) @@ -1108,12 +1245,12 @@ type AddressMetrics # Either TransactionBlockEffects on success, or error on failure. type ExecutionResult { effects: TransactionBlockEffects - errors: String + errors: [String!] } type DryRunResult { transaction: TransactionBlock - errors: String + error: String events: [Event!] results: [DryRunEffect!] @@ -1152,6 +1289,7 @@ type PageInfo { # Checkpoints type CheckpointConnection { edges: [CheckpointEdge!]! + nodes: [Checkpoint!]! pageInfo: PageInfo! } @@ -1163,6 +1301,7 @@ type CheckpointEdge { # Balance type BalanceConnection { edges: [BalanceEdge!]! + nodes: [Balance!]! pageInfo: PageInfo! } @@ -1174,6 +1313,7 @@ type BalanceEdge { # Coin type CoinConnection { edges: [CoinEdge!]! + nodes: [Coin!]! pageInfo: PageInfo! } @@ -1185,6 +1325,7 @@ type CoinEdge { # DynamicField type DynamicFieldConnection { edges: [DynamicFieldEdge!]! + nodes: [DynamicField!]! pageInfo: PageInfo! } @@ -1196,6 +1337,7 @@ type DynamicFieldEdge { # Object type ObjectConnection { edges: [ObjectEdge!]! + nodes: [Object!]! pageInfo: PageInfo! } @@ -1207,6 +1349,7 @@ type ObjectEdge { # MoveObject type MoveObjectConnection { edges: [MoveObjectEdge!]! + nodes: [MoveObject!]! pageInfo: PageInfo! } @@ -1215,9 +1358,22 @@ type MoveObjectEdge { node: MoveObject! } +# MovePackage +type MovePackageConnection { + edges: [MovePackageEdge!]! + nodes: [MovePackage!]! + pageInfo: PageInfo! +} + +type MovePackageEdge { + cursor: String + node: MovePackage! +} + # Event type EventConnection { edges: [EventEdge!]! + nodes: [Event!]! pageInfo: PageInfo! } @@ -1229,6 +1385,7 @@ type EventEdge { # MoveFunction type MoveFunctionConnection { edges: [MoveFunctionEdge!]! + nodes: [MoveFunction!]! pageInfo: PageInfo! } @@ -1240,6 +1397,7 @@ type MoveFunctionEdge { # MoveModuleConnection type MoveModuleConnection { edges: [MoveModuleEdge] + nodes: [MoveModule] pageInfo: PageInfo! } @@ -1251,6 +1409,7 @@ type MoveModuleEdge { # MoveStructConnection type MoveStructConnection { edges: [MoveStructEdge!]! + nodes: [MoveStruct!]! pageInfo: PageInfo! } @@ -1263,6 +1422,7 @@ type MoveStructEdge { type TransactionBlockConnection { totalTransactionBlocks: Int edges: [TransactionBlockEdge!]! + nodes: [TransactionBlock!]! pageInfo: PageInfo! } @@ -1271,9 +1431,58 @@ type TransactionBlockEdge { node: TransactionBlock! } +# TransactionInputConnection +type TransactionInputConnection { + edges: [TransactionInputEdge!]! + nodes: [TransactionInput!]! + pageInfo: PageInfo! +} + +type TransactionInputEdge { + cursor: String + node: TransactionInput! +} + +# ProgrammableTransactionConnection +type ProgrammableTransactionConnection { + edges: [ProgrammableTransactionEdge!]! + nodes: [ProgrammableTransaction!]! + pageInfo: PageInfo! +} + +type ProgrammableTransactionEdge { + cursor: String + node: ProgrammableTransaction! +} + +# ObjectChangeConnection +type ObjectChangeConnection { + edges: [ObjectChangeEdge!]! + nodes: [ObjectChange!]! + pageInfo: PageInfo! +} + +type ObjectChangeEdge { + cursor: String + node: ObjectChange +} + +# BalanceChangeConnection +type BalanceChangeConnection { + edges: [BalanceChangeEdge!]! + nodes: [BalanceChange!]! + pageInfo: PageInfo! +} + +type BalanceChangeEdge { + cursor: String + node: BalanceChange +} + # MoveModuleConnection type MoveModuleConnection { edges: [MoveModuleEdge!]! + nodes: [MoveModule!]! pageInfo: PageInfo! } @@ -1285,6 +1494,7 @@ type MoveModuleEdge { # NameServiceNameConnection type NameServiceNameConnection { edges: [NameServiceNameEdge!]! + nodes: [NameServiceName!]! pageInfo: PageInfo! } @@ -1296,6 +1506,7 @@ type NameServiceNameEdge { # AddressMetricsConnection type AddressMetricsConnection { edges: [AddressMetricEdge!]! + nodes: [AddressMetric!]! pageInfo: PageInfo! } @@ -1304,13 +1515,26 @@ type AddressMetricEdge { node: AddressMetrics! } -# StakeConnection +# StakedSuiConnection type StakedSuiConnection { edges: [StakedSuiEdge!]! + nodes: [StakedSui!]! pageInfo: PageInfo! } -type StakeEdge { +type StakedSuiEdge { cursor: String node: StakedSui! } + +# ValidatorConnection +type ValidatorConnection { + edges: [ValidatorEdge!]! + nodes: [Validator!]! + pageInfo: PageInfo! +} + +type ValidatorEdge { + cursor: String + node: Validator! +} diff --git a/crates/sui-graphql-rpc/src/config.rs b/crates/sui-graphql-rpc/src/config.rs index ef676eb10b6c3..473f46a656b3a 100644 --- a/crates/sui-graphql-rpc/src/config.rs +++ b/crates/sui-graphql-rpc/src/config.rs @@ -188,18 +188,18 @@ impl ServiceConfig { } /// Default number of elements allowed on a single page of a connection. - async fn default_page_size(&self) -> BigInt { - BigInt::from(self.limits.default_page_size) + async fn default_page_size(&self) -> u64 { + self.limits.default_page_size } /// Maximum number of elements allowed on a single page of a connection. - async fn max_page_size(&self) -> BigInt { - BigInt::from(self.limits.max_page_size) + async fn max_page_size(&self) -> u64 { + self.limits.max_page_size } /// Maximum time in milliseconds that will be spent to serve one request. - async fn request_timeout_ms(&self) -> BigInt { - BigInt::from(self.limits.request_timeout_ms) + async fn request_timeout_ms(&self) -> u64 { + self.limits.request_timeout_ms } /// Maximum length of a query payload string. diff --git a/crates/sui-graphql-rpc/src/types/big_int.rs b/crates/sui-graphql-rpc/src/types/big_int.rs index f01e8c8adcae5..51bebb1ee61f0 100644 --- a/crates/sui-graphql-rpc/src/types/big_int.rs +++ b/crates/sui-graphql-rpc/src/types/big_int.rs @@ -11,7 +11,11 @@ use serde::{Deserialize, Serialize}; #[serde(transparent)] pub(crate) struct BigInt(String); -#[Scalar] +#[derive(thiserror::Error, Debug, PartialEq, Eq)] +#[error("The provided string is not a number")] +pub(crate) struct NotANumber; + +#[Scalar(use_type_description = true)] impl ScalarType for BigInt { fn parse(value: Value) -> InputValueResult { match value { @@ -26,9 +30,11 @@ impl ScalarType for BigInt { } } -#[derive(thiserror::Error, Debug, PartialEq, Eq)] -#[error("The provided string is not a number")] -pub(crate) struct NotANumber; +impl Description for BigInt { + fn description() -> &'static str { + "String representation of an arbitrary width, possibly signed integer." + } +} impl FromStr for BigInt { type Err = NotANumber; diff --git a/crates/sui-graphql-rpc/src/types/checkpoint.rs b/crates/sui-graphql-rpc/src/types/checkpoint.rs index 043a751331fa5..9717ce5acc2fb 100644 --- a/crates/sui-graphql-rpc/src/types/checkpoint.rs +++ b/crates/sui-graphql-rpc/src/types/checkpoint.rs @@ -13,6 +13,7 @@ use super::{ }; use async_graphql::{connection::Connection, *}; +/// Filter either by the digest, or the sequence number, or neither, to get the latest checkpoint. #[derive(InputObject)] pub(crate) struct CheckpointId { pub digest: Option, diff --git a/crates/sui-graphql-rpc/src/types/date_time.rs b/crates/sui-graphql-rpc/src/types/date_time.rs index 9ec1dd52569b8..d810c99df104f 100644 --- a/crates/sui-graphql-rpc/src/types/date_time.rs +++ b/crates/sui-graphql-rpc/src/types/date_time.rs @@ -9,12 +9,22 @@ use chrono::{ ParseError as ChronoParseError, }; -// ISO-8601 Date and Time: RFC3339 in UTC -// YYYY-MM-DDTHH:MM:SS.mmmZ #[derive(Clone, Debug, Eq, PartialEq)] pub(crate) struct DateTime(ChronoDateTime); -#[Scalar] +impl DateTime { + pub fn from_ms(timestamp_ms: i64) -> Option { + // TODO: `timestamp_millis_opt` returns an optional to handle ambiguous time conversions + // which UTC does not have, so this should be converted to return a Result, with an + // `InternalError`. + ChronoUtc + .timestamp_millis_opt(timestamp_ms) + .single() + .map(Self) + } +} + +#[Scalar(use_type_description = true)] impl ScalarType for DateTime { fn parse(value: Value) -> InputValueResult { match value { @@ -30,15 +40,9 @@ impl ScalarType for DateTime { } } -impl DateTime { - pub fn from_ms(timestamp_ms: i64) -> Option { - // TODO: `timestamp_millis_opt` returns an optional to handle ambiguous time conversions - // which UTC does not have, so this should be converted to return a Result, with an - // `InternalError`. - ChronoUtc - .timestamp_millis_opt(timestamp_ms) - .single() - .map(Self) +impl Description for DateTime { + fn description() -> &'static str { + "ISO-8601 Date and Time: RFC3339 in UTC with format: YYYY-MM-DDTHH:MM:SS.mmmZ" } } diff --git a/crates/sui-graphql-rpc/src/types/event.rs b/crates/sui-graphql-rpc/src/types/event.rs index 7177fe9101a88..994eb5ac6db78 100644 --- a/crates/sui-graphql-rpc/src/types/event.rs +++ b/crates/sui-graphql-rpc/src/types/event.rs @@ -25,16 +25,12 @@ pub(crate) struct EventFilter { // Enhancement (post-MVP) // after_checkpoint // before_checkpoint - /// Events emitted by a particular package. - /// An event is emitted by a particular package - /// if some function in the package is called - /// by a PTB and emits an event. + /// Events emitted by a particular package. An event is emitted by a particular package if some + /// function in the package is called by a PTB and emits an event. pub emitting_package: Option, - /// Events emitted by a particular Move module. - /// An event is emitted by a particular module - /// if some function in the module is called - /// by a PTB and emits an event. - /// Requires `emitting_package` to be set. + /// Events emitted by a particular Move module. An event is emitted by a particular module if + /// some function in the module is called by a PTB and emits an event. Requires + /// `emitting_package` to be set. pub emitting_module: Option, pub event_package: Option, diff --git a/crates/sui-graphql-rpc/src/types/object.rs b/crates/sui-graphql-rpc/src/types/object.rs index 8901ac5ae626d..054860728a995 100644 --- a/crates/sui-graphql-rpc/src/types/object.rs +++ b/crates/sui-graphql-rpc/src/types/object.rs @@ -41,13 +41,22 @@ pub(crate) enum ObjectKind { #[derive(InputObject, Default, Clone)] pub(crate) struct ObjectFilter { - /// This field is used to specify the type of objects that should be included - /// in the query results. Generic types can be queried by either the generic - /// type name, e.g. `0x2::coin::Coin`, or by the full type name, such as - /// `0x2::coin::Coin<0x2::sui::SUI>`. + /// This field is used to specify the type of objects that should be include in the query + /// results. + /// + /// Type can be filtered by their package, package::module, or their fuly qualified type name. + /// + /// Generic types can be queried by either the generic type name, e.g. `0x2::coin::Coin`, or by + /// the full type name, such as `0x2::coin::Coin<0x2::sui::SUI>`. pub type_: Option, + + /// Filter for live objects by their current owners. pub owner: Option, + + /// Filter for live objects by their IDs. pub object_ids: Option>, + + /// Filter for live or potentially historical objects by their ID and version. pub object_keys: Option>, } diff --git a/crates/sui-graphql-rpc/src/types/open_move_type.rs b/crates/sui-graphql-rpc/src/types/open_move_type.rs index 8922b6b6c3193..53f7ad2040a8d 100644 --- a/crates/sui-graphql-rpc/src/types/open_move_type.rs +++ b/crates/sui-graphql-rpc/src/types/open_move_type.rs @@ -97,13 +97,13 @@ pub(crate) enum OpenMoveTypeSignatureBody { #[Object] impl OpenMoveType { /// Structured representation of the type signature. - async fn signature(&self) -> Option<&OpenMoveTypeSignature> { - Some(&self.signature) + async fn signature(&self) -> &OpenMoveTypeSignature { + &self.signature } /// Flat representation of the type signature, as a displayable string. - async fn repr(&self) -> Option { - Some(self.signature.to_string()) + async fn repr(&self) -> String { + self.signature.to_string() } } diff --git a/crates/sui-graphql-rpc/src/types/query.rs b/crates/sui-graphql-rpc/src/types/query.rs index c06ed8944004e..2770929600fdc 100644 --- a/crates/sui-graphql-rpc/src/types/query.rs +++ b/crates/sui-graphql-rpc/src/types/query.rs @@ -76,6 +76,7 @@ impl Query { Some(Address { address }) } + /// Fetch epoch information by ID (defaults to the latest epoch). async fn epoch(&self, ctx: &Context<'_>, id: Option) -> Result> { if let Some(epoch_id) = id { ctx.data_unchecked::() @@ -92,6 +93,8 @@ impl Query { } } + /// Fetch checkpoint information by sequence number or digest (defaults to the latest available + /// checkpoint). async fn checkpoint( &self, ctx: &Context<'_>, @@ -116,6 +119,7 @@ impl Query { } } + /// Fetch a transaction block by its transaction digest. async fn transaction_block( &self, ctx: &Context<'_>, @@ -205,6 +209,8 @@ impl Query { .extend() } + /// Fetch the protocl config by protocol version (defaults to the latest protocol + /// version known to the GraphQL) async fn protocol_config( &self, ctx: &Context<'_>, diff --git a/crates/sui-graphql-rpc/src/types/sui_address.rs b/crates/sui-graphql-rpc/src/types/sui_address.rs index cf66985af7bcc..f24d007f2dc82 100644 --- a/crates/sui-graphql-rpc/src/types/sui_address.rs +++ b/crates/sui-graphql-rpc/src/types/sui_address.rs @@ -36,21 +36,6 @@ pub(crate) enum FromVecError { WrongLength(usize), } -#[Scalar] -impl ScalarType for SuiAddress { - fn parse(value: Value) -> InputValueResult { - let Value::String(s) = value else { - return Err(InputValueError::expected_type(value)); - }; - - Ok(SuiAddress::from_str(&s)?) - } - - fn to_value(&self) -> Value { - Value::String(format!("0x{}", hex::encode(self.0))) - } -} - impl SuiAddress { pub fn from_array(arr: [u8; SUI_ADDRESS_LENGTH]) -> Self { SuiAddress(arr) @@ -71,6 +56,29 @@ impl SuiAddress { } } +#[Scalar(use_type_description = true)] +impl ScalarType for SuiAddress { + fn parse(value: Value) -> InputValueResult { + let Value::String(s) = value else { + return Err(InputValueError::expected_type(value)); + }; + + Ok(SuiAddress::from_str(&s)?) + } + + fn to_value(&self) -> Value { + Value::String(format!("0x{}", hex::encode(self.0))) + } +} + +impl Description for SuiAddress { + fn description() -> &'static str { + "String containing 32B hex-encoded address, with a leading \"0x\". Leading zeroes can be \ + omitted on input but will always appear in outputs (SuiAddress in output is guaranteed \ + to be 66 characters long)." + } +} + impl TryFrom> for SuiAddress { type Error = FromVecError; diff --git a/crates/sui-graphql-rpc/tests/snapshots/snapshot_tests__schema_sdl_export.snap b/crates/sui-graphql-rpc/tests/snapshots/snapshot_tests__schema_sdl_export.snap index 813b15c2344f3..01d252895ecdc 100644 --- a/crates/sui-graphql-rpc/tests/snapshots/snapshot_tests__schema_sdl_export.snap +++ b/crates/sui-graphql-rpc/tests/snapshots/snapshot_tests__schema_sdl_export.snap @@ -210,6 +210,9 @@ type BalanceEdge { scalar Base64 +""" +String representation of an arbitrary width, possibly signed integer. +""" scalar BigInt @@ -336,6 +339,9 @@ type CheckpointEdge { cursor: String! } +""" +Filter either by the digest, or the sequence number, or neither, to get the latest checkpoint. +""" input CheckpointId { digest: String sequenceNumber: Int @@ -438,6 +444,9 @@ type ConsensusCommitPrologueTransaction { consensusCommitDigest: String } +""" +ISO-8601 Date and Time: RFC3339 in UTC with format: YYYY-MM-DDTHH:MM:SS.mmmZ +""" scalar DateTime type DynamicField { @@ -689,18 +698,14 @@ input EventFilter { sender: SuiAddress transactionDigest: String """ - Events emitted by a particular package. - An event is emitted by a particular package - if some function in the package is called - by a PTB and emits an event. + Events emitted by a particular package. An event is emitted by a particular package if some + function in the package is called by a PTB and emits an event. """ emittingPackage: SuiAddress """ - Events emitted by a particular Move module. - An event is emitted by a particular module - if some function in the module is called - by a PTB and emits an event. - Requires `emitting_package` to be set. + Events emitted by a particular Move module. An event is emitted by a particular module if + some function in the module is called by a PTB and emits an event. Requires + `emitting_package` to be set. """ emittingModule: String eventPackage: SuiAddress @@ -1484,14 +1489,26 @@ type ObjectEdge { input ObjectFilter { """ - This field is used to specify the type of objects that should be included - in the query results. Generic types can be queried by either the generic - type name, e.g. `0x2::coin::Coin`, or by the full type name, such as - `0x2::coin::Coin<0x2::sui::SUI>`. + This field is used to specify the type of objects that should be include in the query + results. + + Type can be filtered by their package, package::module, or their fuly qualified type name. + + Generic types can be queried by either the generic type name, e.g. `0x2::coin::Coin`, or by + the full type name, such as `0x2::coin::Coin<0x2::sui::SUI>`. """ type: String + """ + Filter for live objects by their current owners. + """ owner: SuiAddress + """ + Filter for live objects by their IDs. + """ objectIds: [SuiAddress!] + """ + Filter for live or potentially historical objects by their ID and version. + """ objectKeys: [ObjectKey!] } @@ -1528,11 +1545,11 @@ type OpenMoveType { """ Structured representation of the type signature. """ - signature: OpenMoveTypeSignature + signature: OpenMoveTypeSignature! """ Flat representation of the type signature, as a displayable string. """ - repr: String + repr: String! } """ @@ -1776,8 +1793,18 @@ type Query { owner(address: SuiAddress!): ObjectOwner object(address: SuiAddress!, version: Int): Object address(address: SuiAddress!): Address + """ + Fetch epoch information by ID (defaults to the latest epoch). + """ epoch(id: Int): Epoch + """ + Fetch checkpoint information by sequence number or digest (defaults to the latest available + checkpoint). + """ checkpoint(id: CheckpointId): Checkpoint + """ + Fetch a transaction block by its transaction digest. + """ transactionBlock(digest: String!): TransactionBlock """ The coin objects that exist in the network. @@ -1790,6 +1817,10 @@ type Query { transactionBlockConnection(first: Int, after: String, last: Int, before: String, filter: TransactionBlockFilter): TransactionBlockConnection eventConnection(first: Int, after: String, last: Int, before: String, filter: EventFilter): EventConnection objectConnection(first: Int, after: String, last: Int, before: String, filter: ObjectFilter): ObjectConnection + """ + Fetch the protocl config by protocol version (defaults to the latest protocol + version known to the GraphQL) + """ protocolConfig(protocolVersion: Int): ProtocolConfigs! """ Resolves the owner address of the provided domain name @@ -1894,15 +1925,15 @@ type ServiceConfig { """ Default number of elements allowed on a single page of a connection. """ - defaultPageSize: BigInt! + defaultPageSize: Int! """ Maximum number of elements allowed on a single page of a connection. """ - maxPageSize: BigInt! + maxPageSize: Int! """ Maximum time in milliseconds that will be spent to serve one request. """ - requestTimeoutMs: BigInt! + requestTimeoutMs: Int! """ Maximum length of a query payload string. """ @@ -2069,6 +2100,9 @@ type StorageFund { } +""" +String containing 32B hex-encoded address, with a leading "0x". Leading zeroes can be omitted on input but will always appear in outputs (SuiAddress in output is guaranteed to be 66 characters long). +""" scalar SuiAddress """