diff --git a/crates/sui-graphql-e2e-tests/tests/transactions/filters/transaction_ids.exp b/crates/sui-graphql-e2e-tests/tests/transactions/filters/transaction_ids.exp index c82dc61b59424..68ccdaff1ab7f 100644 --- a/crates/sui-graphql-e2e-tests/tests/transactions/filters/transaction_ids.exp +++ b/crates/sui-graphql-e2e-tests/tests/transactions/filters/transaction_ids.exp @@ -86,8 +86,8 @@ Response: { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, - "endCursor": null, - "startCursor": null + "endCursor": "eyJjIjoyLCJ0IjoyLCJpIjp0cnVlfQ", + "startCursor": "eyJjIjoyLCJ0IjowLCJpIjp0cnVlfQ" }, "nodes": [] } diff --git a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/first.exp b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/first.exp index 484d16a2d38be..f5adb54b34462 100644 --- a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/first.exp +++ b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/first.exp @@ -1,175 +1,150 @@ -processed 22 tasks +processed 25 tasks init: A: object(0,0), B: object(0,1) -task 1, lines 6-27: +task 1, lines 9-30: //# publish created: object(1,0) mutated: object(0,2) gas summary: computation_cost: 1000000, storage_cost: 5798800, storage_rebate: 0, non_refundable_storage_fee: 0 -task 2, line 29: +task 2, line 32: //# create-checkpoint Checkpoint created: 1 -task 3, line 31: -//# run Test::M1::create --args 0 @A --sender A +task 3, line 34: +//# run Test::M1::create --args 0 @B --sender A created: object(3,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 0, non_refundable_storage_fee: 0 -task 4, line 33: +task 4, line 36: //# run Test::M1::create --args 1 @A --sender A created: object(4,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 5, line 35: -//# run Test::M1::create --args 2 @A --sender A +task 5, line 38: +//# run Test::M1::create --args 2 @B --sender A created: object(5,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 6, line 37: +task 6, line 40: //# run Test::M1::create --args 3 @A --sender A created: object(6,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 7, line 39: -//# run Test::M1::create --args 4 @A --sender A +task 7, line 42: +//# run Test::M1::create --args 4 @B --sender A created: object(7,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 8, line 41: +task 8, line 44: //# create-checkpoint Checkpoint created: 2 -task 9, line 43: +task 9, line 46: //# run Test::M1::create --args 100 @A --sender A created: object(9,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 10, line 45: +task 10, line 48: //# run Test::M1::create --args 101 @A --sender A created: object(10,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 11, line 47: +task 11, line 50: //# run Test::M1::create --args 102 @A --sender A created: object(11,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 12, line 49: -//# run Test::M1::create --args 103 @A --sender A +task 12, line 52: +//# run Test::M1::create --args 103 @B --sender A created: object(12,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 13, line 51: -//# run Test::M1::create --args 104 @A --sender A +task 13, line 54: +//# run Test::M1::create --args 104 @B --sender A created: object(13,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 14, line 53: +task 14, line 56: //# create-checkpoint Checkpoint created: 3 -task 15, lines 55-74: +task 15, lines 58-82: //# run-graphql Response: { "data": { "transactionBlocks": { "pageInfo": { - "hasNextPage": false, "hasPreviousPage": false, - "endCursor": "eyJjIjozLCJ0IjoxMSwiaSI6ZmFsc2V9", - "startCursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0" + "hasNextPage": false, + "startCursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0", + "endCursor": "eyJjIjozLCJ0IjoxMSwiaSI6ZmFsc2V9" }, - "nodes": [ - { - "digest": "CReUjLynvpq4dD4w6zekGxvSyBBQF2e3KG3K2Rs7oD8L", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - }, - { - "digest": "BB6bMUxrBJX9wANzzptKnJM3bMVFKnD4xtY8DGWthaH9", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - }, - { - "digest": "Hs7VPKSy8mba36pvKiSPu3yoLVxvFZNHivc1Kr2kNrjv", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - }, - { - "digest": "BWYXBZPBViYGGRwCvN5oVjVWgFoHm1jdhiuAH7CEqcYX", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - }, - { - "digest": "FL9BoCUhPstZG4fyQV9scjS8GGBfFSsybB44VTzkidmh", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - }, + "edges": [ { - "digest": "2fkJPVgstXd828Jofx3MpMmK1BVBc2gTYbaQCHEgfWQ5", - "effects": { - "checkpoint": { - "sequenceNumber": 3 + "cursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0", + "node": { + "digest": "HzyC8gcn4m1ymKxYSpWMaNnmbrqm4hX7UBteJ4me3LFd", + "effects": { + "checkpoint": { + "sequenceNumber": 2 + } } } }, { - "digest": "FLACNu1N2FiLXK7Znvdky5z3P4qvzP1WVwcwHbenrYyT", - "effects": { - "checkpoint": { - "sequenceNumber": 3 + "cursor": "eyJjIjozLCJ0Ijo0LCJpIjpmYWxzZX0", + "node": { + "digest": "6RKZYt946ztfY8ZVspCv8faXBzKxDcTUEHnrCyBSZ4Li", + "effects": { + "checkpoint": { + "sequenceNumber": 2 + } } } }, { - "digest": "2faB3pdjTjZR2Y6F6p3w3xB6cBY9LEuoxPNRSquZGWLL", - "effects": { - "checkpoint": { - "sequenceNumber": 3 + "cursor": "eyJjIjozLCJ0Ijo2LCJpIjpmYWxzZX0", + "node": { + "digest": "83AZLnLVtQeUdrXGg3igLkeo94j3wTLuwY4izobLLVBT", + "effects": { + "checkpoint": { + "sequenceNumber": 2 + } } } }, { - "digest": "7b1t2Z9dNq695LRtuz8air1mQ3KQnonPbNu3G6yMifvS", - "effects": { - "checkpoint": { - "sequenceNumber": 3 + "cursor": "eyJjIjozLCJ0IjoxMCwiaSI6ZmFsc2V9", + "node": { + "digest": "AWWgnnumcijVEY2YUzs4MtqzFPeLKFAbHnnjXwUyn6Gj", + "effects": { + "checkpoint": { + "sequenceNumber": 3 + } } } }, { - "digest": "2aaupMmejUPdfcLpbyjcNGRz4hL6tBBJ9TGfDfzF3Hew", - "effects": { - "checkpoint": { - "sequenceNumber": 3 + "cursor": "eyJjIjozLCJ0IjoxMSwiaSI6ZmFsc2V9", + "node": { + "digest": "DVVVd1cLYDpV3KHhXpirV5NFpk3DKaCuKvXXFeG2owA7", + "effects": { + "checkpoint": { + "sequenceNumber": 3 + } } } } @@ -178,23 +153,26 @@ Response: { } } -task 16, lines 77-97: +task 16, lines 85-111: //# run-graphql Response: { "data": { "transactionBlocks": { "pageInfo": { - "hasNextPage": true, "hasPreviousPage": false, - "endCursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0", - "startCursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0" + "hasNextPage": true, + "startCursor": "eyJjIjozLCJ0IjoyLCJpIjp0cnVlfQ", + "endCursor": "eyJjIjozLCJ0IjozLCJpIjp0cnVlfQ" }, - "nodes": [ + "edges": [ { - "digest": "CReUjLynvpq4dD4w6zekGxvSyBBQF2e3KG3K2Rs7oD8L", - "effects": { - "checkpoint": { - "sequenceNumber": 2 + "cursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0", + "node": { + "digest": "HzyC8gcn4m1ymKxYSpWMaNnmbrqm4hX7UBteJ4me3LFd", + "effects": { + "checkpoint": { + "sequenceNumber": 2 + } } } } @@ -203,23 +181,26 @@ Response: { } } -task 17, lines 99-118: -//# run-graphql --cursors {"c":4,"t":2,"i":false} +task 17, lines 113-137: +//# run-graphql --cursors {"c":4,"t":3,"i":true} Response: { "data": { "transactionBlocks": { "pageInfo": { - "hasNextPage": true, "hasPreviousPage": true, - "endCursor": "eyJjIjo0LCJ0IjozLCJpIjpmYWxzZX0", - "startCursor": "eyJjIjo0LCJ0IjozLCJpIjpmYWxzZX0" + "hasNextPage": true, + "startCursor": "eyJjIjo0LCJ0Ijo0LCJpIjp0cnVlfQ", + "endCursor": "eyJjIjo0LCJ0Ijo0LCJpIjp0cnVlfQ" }, - "nodes": [ + "edges": [ { - "digest": "BB6bMUxrBJX9wANzzptKnJM3bMVFKnD4xtY8DGWthaH9", - "effects": { - "checkpoint": { - "sequenceNumber": 2 + "cursor": "eyJjIjo0LCJ0Ijo0LCJpIjpmYWxzZX0", + "node": { + "digest": "6RKZYt946ztfY8ZVspCv8faXBzKxDcTUEHnrCyBSZ4Li", + "effects": { + "checkpoint": { + "sequenceNumber": 2 + } } } } @@ -228,23 +209,26 @@ Response: { } } -task 18, lines 120-139: -//# run-graphql --cursors {"c":4,"t":6,"i":false} +task 18, lines 139-165: +//# run-graphql --cursors {"c":4,"t":4,"i":true} Response: { "data": { "transactionBlocks": { "pageInfo": { - "hasNextPage": true, "hasPreviousPage": true, - "endCursor": "eyJjIjo0LCJ0Ijo3LCJpIjpmYWxzZX0", - "startCursor": "eyJjIjo0LCJ0Ijo3LCJpIjpmYWxzZX0" + "hasNextPage": true, + "startCursor": "eyJjIjo0LCJ0Ijo1LCJpIjp0cnVlfQ", + "endCursor": "eyJjIjo0LCJ0Ijo3LCJpIjp0cnVlfQ" }, - "nodes": [ + "edges": [ { - "digest": "2fkJPVgstXd828Jofx3MpMmK1BVBc2gTYbaQCHEgfWQ5", - "effects": { - "checkpoint": { - "sequenceNumber": 3 + "cursor": "eyJjIjo0LCJ0Ijo2LCJpIjpmYWxzZX0", + "node": { + "digest": "83AZLnLVtQeUdrXGg3igLkeo94j3wTLuwY4izobLLVBT", + "effects": { + "checkpoint": { + "sequenceNumber": 2 + } } } } @@ -253,23 +237,53 @@ Response: { } } -task 19, lines 141-160: -//# run-graphql --cursors {"c":4,"t":10,"i":false} +task 19, lines 167-193: +//# run-graphql --cursors {"c":4,"t":7,"i":true} Response: { "data": { "transactionBlocks": { "pageInfo": { - "hasNextPage": false, "hasPreviousPage": true, - "endCursor": "eyJjIjo0LCJ0IjoxMSwiaSI6ZmFsc2V9", - "startCursor": "eyJjIjo0LCJ0IjoxMSwiaSI6ZmFsc2V9" + "hasNextPage": true, + "startCursor": "eyJjIjo0LCJ0Ijo4LCJpIjp0cnVlfQ", + "endCursor": "eyJjIjo0LCJ0Ijo5LCJpIjp0cnVlfQ" }, - "nodes": [ + "edges": [] + } + } +} + +task 20, lines 195-220: +//# run-graphql --cursors {"c":4,"t":9,"i":true} +Response: { + "data": { + "transactionBlocks": { + "pageInfo": { + "hasPreviousPage": true, + "hasNextPage": false, + "startCursor": "eyJjIjo0LCJ0IjoxMCwiaSI6dHJ1ZX0", + "endCursor": "eyJjIjo0LCJ0IjoxMSwiaSI6dHJ1ZX0" + }, + "edges": [ + { + "cursor": "eyJjIjo0LCJ0IjoxMCwiaSI6ZmFsc2V9", + "node": { + "digest": "AWWgnnumcijVEY2YUzs4MtqzFPeLKFAbHnnjXwUyn6Gj", + "effects": { + "checkpoint": { + "sequenceNumber": 3 + } + } + } + }, { - "digest": "2aaupMmejUPdfcLpbyjcNGRz4hL6tBBJ9TGfDfzF3Hew", - "effects": { - "checkpoint": { - "sequenceNumber": 3 + "cursor": "eyJjIjo0LCJ0IjoxMSwiaSI6ZmFsc2V9", + "node": { + "digest": "DVVVd1cLYDpV3KHhXpirV5NFpk3DKaCuKvXXFeG2owA7", + "effects": { + "checkpoint": { + "sequenceNumber": 3 + } } } } @@ -278,34 +292,67 @@ Response: { } } -task 20, lines 162-181: -//# run-graphql --cursors {"c":4,"t":11,"i":false} +task 21, line 222: +//# run Test::M1::create --args 105 @A --sender A +created: object(21,0) +mutated: object(0,0) +gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 + +task 22, line 224: +//# create-checkpoint +Checkpoint created: 4 + +task 23, lines 226-252: +//# run-graphql --cursors {"c":4,"t":11,"i":true} Response: { "data": { "transactionBlocks": { "pageInfo": { + "hasPreviousPage": true, "hasNextPage": false, - "hasPreviousPage": false, - "endCursor": null, - "startCursor": null + "startCursor": "eyJjIjo0LCJ0IjoxMiwiaSI6dHJ1ZX0", + "endCursor": "eyJjIjo0LCJ0IjoxMiwiaSI6dHJ1ZX0" }, - "nodes": [] + "edges": [] } } } -task 21, lines 183-202: -//# run-graphql --cursors {"c":4,"t":12,"i":false} +task 24, lines 254-279: +//# run-graphql --cursors {"c":4,"t":12,"i":true} Response: { "data": { "transactionBlocks": { "pageInfo": { + "hasPreviousPage": true, "hasNextPage": false, - "hasPreviousPage": false, - "endCursor": null, - "startCursor": null + "startCursor": "eyJjIjo0LCJ0IjoxMCwiaSI6dHJ1ZX0", + "endCursor": "eyJjIjo0LCJ0IjoxMSwiaSI6dHJ1ZX0" }, - "nodes": [] + "edges": [ + { + "cursor": "eyJjIjo0LCJ0IjoxMCwiaSI6ZmFsc2V9", + "node": { + "digest": "AWWgnnumcijVEY2YUzs4MtqzFPeLKFAbHnnjXwUyn6Gj", + "effects": { + "checkpoint": { + "sequenceNumber": 3 + } + } + } + }, + { + "cursor": "eyJjIjo0LCJ0IjoxMSwiaSI6ZmFsc2V9", + "node": { + "digest": "DVVVd1cLYDpV3KHhXpirV5NFpk3DKaCuKvXXFeG2owA7", + "effects": { + "checkpoint": { + "sequenceNumber": 3 + } + } + } + } + ] } } } diff --git a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/first.move b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/first.move index b1feff551c065..acfdbc75cde47 100644 --- a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/first.move +++ b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/first.move @@ -1,6 +1,9 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 +// Tests paginating forwards where first and scanLimit are equal. The 1st, 3rd, 5th, and 7th through +// 10th transactions will match the filtering criteria. + //# init --protocol-version 48 --addresses Test=0x0 --accounts A B --simulator //# publish @@ -28,15 +31,15 @@ module Test::M1 { //# create-checkpoint -//# run Test::M1::create --args 0 @A --sender A +//# run Test::M1::create --args 0 @B --sender A //# run Test::M1::create --args 1 @A --sender A -//# run Test::M1::create --args 2 @A --sender A +//# run Test::M1::create --args 2 @B --sender A //# run Test::M1::create --args 3 @A --sender A -//# run Test::M1::create --args 4 @A --sender A +//# run Test::M1::create --args 4 @B --sender A //# create-checkpoint @@ -46,27 +49,32 @@ module Test::M1 { //# run Test::M1::create --args 102 @A --sender A -//# run Test::M1::create --args 103 @A --sender A +//# run Test::M1::create --args 103 @B --sender A -//# run Test::M1::create --args 104 @A --sender A +//# run Test::M1::create --args 104 @B --sender A //# create-checkpoint //# run-graphql -# Expect ten results +# Expect 7 results +# [2, 3, 4, 5, 6, 7, 8, 9, 10, 11] <- tx_sequence_number +# [B, A, B, A, B, A, A, A, B, B] { - transactionBlocks(first: 50 filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(first: 50 filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } - nodes { - digest - effects { - checkpoint { - sequenceNumber + edges { + cursor + node { + digest + effects { + checkpoint { + sequenceNumber + } } } } @@ -75,126 +83,195 @@ module Test::M1 { //# run-graphql -# With a scanLimit of 1, we should get a transaction whose digest corresponds to the first of the -# previous result, and `hasNextPage` should be true +# scans [B, A] -> [2, 3] +# Because `scanLimit` is specified, both the start and end cursors should have `is_scan_limited` flag to true +# startCursor is at 2, endCursor is at 3 +# The cursor for the node will have `is_scan_limited` flag set to false, because we know for sure there is +# a corresponding element for the cursor in the result set. { - transactionBlocks(first: 1 scanLimit: 1 filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(first: 2 scanLimit: 2 filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } - nodes { - digest - effects { - checkpoint { - sequenceNumber + edges { + cursor + node { + digest + effects { + checkpoint { + sequenceNumber + } } } } } } -//# run-graphql --cursors {"c":4,"t":2,"i":false} -# The query fetches the second transaction from the list of ten +//# run-graphql --cursors {"c":4,"t":3,"i":true} +# scans [B] -> [4] +# Still paginating with `scanLimit`, both the start and end cursors should have `is_scan_limited` flag to true +# because of the scanLimit of 4, startCursor = endCursor = 4 { - transactionBlocks(first: 1 scanLimit: 1 after: "@{cursor_0}" filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(first: 1 scanLimit: 1 after: "@{cursor_0}" filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } - nodes { - digest - effects { - checkpoint { - sequenceNumber + edges { + cursor + node { + digest + effects { + checkpoint { + sequenceNumber + } } } } } } -//# run-graphql --cursors {"c":4,"t":6,"i":false} -# The query fetches the sixth transaction from the set, also the first transaction from checkpoint 3 +//# run-graphql --cursors {"c":4,"t":4,"i":true} +# scans [A, B, A] -> [5, 6, 7] +# both the start and end cursors should have `is_scan_limited` flag to true +# startCursor at 5, the sole element has cursor at 6, endCursor at 7 +# instead of wrapping around the result set, the boundary cursors are pushed out +# to the first and last transaction scanned in this query { - transactionBlocks(first: 1 scanLimit: 1 after: "@{cursor_0}" filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(first: 3 scanLimit: 3 after: "@{cursor_0}" filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } - nodes { - digest - effects { - checkpoint { - sequenceNumber + edges { + cursor + node { + digest + effects { + checkpoint { + sequenceNumber + } } } } } } -//# run-graphql --cursors {"c":4,"t":10,"i":false} -# Fetches the last transaction, hasPrevPage is true, hasNextPage is false +//# run-graphql --cursors {"c":4,"t":7,"i":true} +# scans [A, A] -> [8, 9] +# both the start and end cursors should have `is_scan_limited` flag to true +# startCursor at 5, the sole element has cursor at 8, endCursor at 9 +# instead of returninng None, we set the boundary cursors +# to the first and last transaction scanned in this query { - transactionBlocks(first: 1 scanLimit: 1 after: "@{cursor_0}" filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(first: 2 scanLimit: 2 after: "@{cursor_0}" filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } - nodes { - digest - effects { - checkpoint { - sequenceNumber + edges { + cursor + node { + digest + effects { + checkpoint { + sequenceNumber + } } } } } } -//# run-graphql --cursors {"c":4,"t":11,"i":false} -# Should yield no results, no cursors, and both pages are false +//# run-graphql --cursors {"c":4,"t":9,"i":true} +# scans [B, B] -> [10, 11] +# both the start and end cursors should have `is_scan_limited` flag to true +# startCursor at 10, endCursor at 11 +# correctly detects we've reached the end of the upper bound { - transactionBlocks(first: 1 scanLimit: 1 after: "@{cursor_0}" filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(first: 2 scanLimit: 2 after: "@{cursor_0}" filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } - nodes { - digest - effects { - checkpoint { - sequenceNumber + edges { + cursor + node { + digest + effects { + checkpoint { + sequenceNumber + } } } } } } -//# run-graphql --cursors {"c":4,"t":12,"i":false} -# Should yield no results, no cursors, and both pages are false +//# run Test::M1::create --args 105 @A --sender A + +//# create-checkpoint + +//# run-graphql --cursors {"c":4,"t":11,"i":true} +# we've introduced a new final transaction that doesn't match the filter +# both the start and end cursors should have `is_scan_limited` flag to true +# startCursor = endCursor = 12, because there is only 1 more from the given cursor, +# regardless of the specified scanLimit +# correctly detects we've reached the end of the upper bound { - transactionBlocks(first: 1 scanLimit: 1 after: "@{cursor_0}" filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(first: 2 scanLimit: 2 after: "@{cursor_0}" filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 5}) { pageInfo { - hasNextPage hasPreviousPage + hasNextPage + startCursor endCursor + } + edges { + cursor + node { + digest + effects { + checkpoint { + sequenceNumber + } + } + } + } + } +} + +//# run-graphql --cursors {"c":4,"t":12,"i":true} +# try paginating backwards on the last `endCursor` +# should yield startCursor at 10, endCursor at 11 +# and the result set consists of txs 10 and 11 +# the scanLimit is exclusive of the cursor, hence we reach tx 10 inclusively +{ + transactionBlocks(last: 2 scanLimit: 2 before: "@{cursor_0}" filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 5}) { + pageInfo { + hasPreviousPage + hasNextPage startCursor + endCursor } - nodes { - digest - effects { - checkpoint { - sequenceNumber + edges { + cursor + node { + digest + effects { + checkpoint { + sequenceNumber + } } } } diff --git a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/last.exp b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/last.exp index 81af9a89f362f..e2b301c1dc7e3 100644 --- a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/last.exp +++ b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/last.exp @@ -3,173 +3,148 @@ processed 22 tasks init: A: object(0,0), B: object(0,1) -task 1, lines 6-27: +task 1, lines 8-29: //# publish created: object(1,0) mutated: object(0,2) gas summary: computation_cost: 1000000, storage_cost: 5798800, storage_rebate: 0, non_refundable_storage_fee: 0 -task 2, line 29: +task 2, line 31: //# create-checkpoint Checkpoint created: 1 -task 3, line 31: -//# run Test::M1::create --args 0 @A --sender A +task 3, line 33: +//# run Test::M1::create --args 0 @B --sender A created: object(3,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 0, non_refundable_storage_fee: 0 -task 4, line 33: -//# run Test::M1::create --args 1 @A --sender A +task 4, line 35: +//# run Test::M1::create --args 1 @B --sender A created: object(4,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 5, line 35: +task 5, line 37: //# run Test::M1::create --args 2 @A --sender A created: object(5,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 6, line 37: +task 6, line 39: //# run Test::M1::create --args 3 @A --sender A created: object(6,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 7, line 39: +task 7, line 41: //# run Test::M1::create --args 4 @A --sender A created: object(7,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 8, line 41: +task 8, line 43: //# create-checkpoint Checkpoint created: 2 -task 9, line 43: -//# run Test::M1::create --args 100 @A --sender A +task 9, line 45: +//# run Test::M1::create --args 100 @B --sender A created: object(9,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 10, line 45: +task 10, line 47: //# run Test::M1::create --args 101 @A --sender A created: object(10,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 11, line 47: -//# run Test::M1::create --args 102 @A --sender A +task 11, line 49: +//# run Test::M1::create --args 102 @B --sender A created: object(11,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 12, line 49: +task 12, line 51: //# run Test::M1::create --args 103 @A --sender A created: object(12,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 13, line 51: -//# run Test::M1::create --args 104 @A --sender A +task 13, line 53: +//# run Test::M1::create --args 104 @B --sender A created: object(13,0) mutated: object(0,0) gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 -task 14, line 53: +task 14, line 55: //# create-checkpoint Checkpoint created: 3 -task 15, lines 55-74: +task 15, lines 57-79: //# run-graphql Response: { "data": { "transactionBlocks": { "pageInfo": { - "hasNextPage": false, "hasPreviousPage": false, - "endCursor": "eyJjIjozLCJ0IjoxMSwiaSI6ZmFsc2V9", - "startCursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0" + "hasNextPage": false, + "startCursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0", + "endCursor": "eyJjIjozLCJ0IjoxMSwiaSI6ZmFsc2V9" }, - "nodes": [ - { - "digest": "CReUjLynvpq4dD4w6zekGxvSyBBQF2e3KG3K2Rs7oD8L", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - }, - { - "digest": "BB6bMUxrBJX9wANzzptKnJM3bMVFKnD4xtY8DGWthaH9", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - }, - { - "digest": "Hs7VPKSy8mba36pvKiSPu3yoLVxvFZNHivc1Kr2kNrjv", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - }, - { - "digest": "BWYXBZPBViYGGRwCvN5oVjVWgFoHm1jdhiuAH7CEqcYX", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - }, - { - "digest": "FL9BoCUhPstZG4fyQV9scjS8GGBfFSsybB44VTzkidmh", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - }, + "edges": [ { - "digest": "2fkJPVgstXd828Jofx3MpMmK1BVBc2gTYbaQCHEgfWQ5", - "effects": { - "checkpoint": { - "sequenceNumber": 3 + "cursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0", + "node": { + "digest": "HzyC8gcn4m1ymKxYSpWMaNnmbrqm4hX7UBteJ4me3LFd", + "effects": { + "checkpoint": { + "sequenceNumber": 2 + } } } }, { - "digest": "FLACNu1N2FiLXK7Znvdky5z3P4qvzP1WVwcwHbenrYyT", - "effects": { - "checkpoint": { - "sequenceNumber": 3 + "cursor": "eyJjIjozLCJ0IjozLCJpIjpmYWxzZX0", + "node": { + "digest": "DiywoRFzC33smQhVf5K7AcM853XFgfgFxBGErLTEvVWi", + "effects": { + "checkpoint": { + "sequenceNumber": 2 + } } } }, { - "digest": "2faB3pdjTjZR2Y6F6p3w3xB6cBY9LEuoxPNRSquZGWLL", - "effects": { - "checkpoint": { - "sequenceNumber": 3 + "cursor": "eyJjIjozLCJ0Ijo3LCJpIjpmYWxzZX0", + "node": { + "digest": "F32vrNL7p5sa1iFeykvFQ17UYLeM1urXnSNbbGyoqDRx", + "effects": { + "checkpoint": { + "sequenceNumber": 3 + } } } }, { - "digest": "7b1t2Z9dNq695LRtuz8air1mQ3KQnonPbNu3G6yMifvS", - "effects": { - "checkpoint": { - "sequenceNumber": 3 + "cursor": "eyJjIjozLCJ0Ijo5LCJpIjpmYWxzZX0", + "node": { + "digest": "3eHY9XENiqep4VvNBr3ws79TEMGhp5egGvFEymk679dc", + "effects": { + "checkpoint": { + "sequenceNumber": 3 + } } } }, { - "digest": "2aaupMmejUPdfcLpbyjcNGRz4hL6tBBJ9TGfDfzF3Hew", - "effects": { - "checkpoint": { - "sequenceNumber": 3 + "cursor": "eyJjIjozLCJ0IjoxMSwiaSI6ZmFsc2V9", + "node": { + "digest": "4p5avK1cStj1xtBnvCnHgEUVVr5qnfXQ76ujUZx4ZvP8", + "effects": { + "checkpoint": { + "sequenceNumber": 3 + } } } } @@ -178,22 +153,22 @@ Response: { } } -task 16, lines 77-100: +task 16, lines 82-106: //# run-graphql Response: { "data": { "transactionBlocks": { "pageInfo": { - "hasNextPage": false, "hasPreviousPage": true, - "endCursor": "eyJjIjozLCJ0IjoxMSwiaSI6ZmFsc2V9", - "startCursor": "eyJjIjozLCJ0IjoxMSwiaSI6ZmFsc2V9" + "hasNextPage": false, + "startCursor": "eyJjIjozLCJ0IjoxMCwiaSI6dHJ1ZX0", + "endCursor": "eyJjIjozLCJ0IjoxMSwiaSI6dHJ1ZX0" }, "edges": [ { "cursor": "eyJjIjozLCJ0IjoxMSwiaSI6ZmFsc2V9", "node": { - "digest": "2aaupMmejUPdfcLpbyjcNGRz4hL6tBBJ9TGfDfzF3Hew", + "digest": "4p5avK1cStj1xtBnvCnHgEUVVr5qnfXQ76ujUZx4ZvP8", "effects": { "checkpoint": { "sequenceNumber": 3 @@ -206,22 +181,22 @@ Response: { } } -task 17, lines 102-124: -//# run-graphql --cursors {"c":4,"t":11,"i":false} +task 17, lines 108-132: +//# run-graphql --cursors {"c":4,"t":10,"i":true} Response: { "data": { "transactionBlocks": { "pageInfo": { - "hasNextPage": true, "hasPreviousPage": true, - "endCursor": "eyJjIjo0LCJ0IjoxMCwiaSI6ZmFsc2V9", - "startCursor": "eyJjIjo0LCJ0IjoxMCwiaSI6ZmFsc2V9" + "hasNextPage": true, + "startCursor": "eyJjIjo0LCJ0Ijo5LCJpIjp0cnVlfQ", + "endCursor": "eyJjIjo0LCJ0Ijo5LCJpIjp0cnVlfQ" }, "edges": [ { - "cursor": "eyJjIjo0LCJ0IjoxMCwiaSI6ZmFsc2V9", + "cursor": "eyJjIjo0LCJ0Ijo5LCJpIjpmYWxzZX0", "node": { - "digest": "7b1t2Z9dNq695LRtuz8air1mQ3KQnonPbNu3G6yMifvS", + "digest": "3eHY9XENiqep4VvNBr3ws79TEMGhp5egGvFEymk679dc", "effects": { "checkpoint": { "sequenceNumber": 3 @@ -234,25 +209,25 @@ Response: { } } -task 18, lines 126-148: -//# run-graphql --cursors {"c":4,"t":7,"i":false} +task 18, lines 134-158: +//# run-graphql --cursors {"c":4,"t":9,"i":true} Response: { "data": { "transactionBlocks": { "pageInfo": { - "hasNextPage": true, "hasPreviousPage": true, - "endCursor": "eyJjIjo0LCJ0Ijo2LCJpIjpmYWxzZX0", - "startCursor": "eyJjIjo0LCJ0Ijo2LCJpIjpmYWxzZX0" + "hasNextPage": true, + "startCursor": "eyJjIjo0LCJ0Ijo2LCJpIjp0cnVlfQ", + "endCursor": "eyJjIjo0LCJ0Ijo4LCJpIjp0cnVlfQ" }, "edges": [ { - "cursor": "eyJjIjo0LCJ0Ijo2LCJpIjpmYWxzZX0", + "cursor": "eyJjIjo0LCJ0Ijo3LCJpIjpmYWxzZX0", "node": { - "digest": "FL9BoCUhPstZG4fyQV9scjS8GGBfFSsybB44VTzkidmh", + "digest": "F32vrNL7p5sa1iFeykvFQ17UYLeM1urXnSNbbGyoqDRx", "effects": { "checkpoint": { - "sequenceNumber": 2 + "sequenceNumber": 3 } } } @@ -262,22 +237,49 @@ Response: { } } -task 19, lines 150-172: -//# run-graphql --cursors {"c":4,"t":3,"i":false} +task 19, lines 160-184: +//# run-graphql --cursors {"c":4,"t":6,"i":true} Response: { "data": { "transactionBlocks": { "pageInfo": { + "hasPreviousPage": true, "hasNextPage": true, + "startCursor": "eyJjIjo0LCJ0Ijo0LCJpIjp0cnVlfQ", + "endCursor": "eyJjIjo0LCJ0Ijo1LCJpIjp0cnVlfQ" + }, + "edges": [] + } + } +} + +task 20, lines 186-209: +//# run-graphql --cursors {"c":4,"t":4,"i":true} +Response: { + "data": { + "transactionBlocks": { + "pageInfo": { "hasPreviousPage": false, - "endCursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0", - "startCursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0" + "hasNextPage": true, + "startCursor": "eyJjIjo0LCJ0IjoyLCJpIjp0cnVlfQ", + "endCursor": "eyJjIjo0LCJ0IjozLCJpIjp0cnVlfQ" }, "edges": [ { "cursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0", "node": { - "digest": "CReUjLynvpq4dD4w6zekGxvSyBBQF2e3KG3K2Rs7oD8L", + "digest": "HzyC8gcn4m1ymKxYSpWMaNnmbrqm4hX7UBteJ4me3LFd", + "effects": { + "checkpoint": { + "sequenceNumber": 2 + } + } + } + }, + { + "cursor": "eyJjIjo0LCJ0IjozLCJpIjpmYWxzZX0", + "node": { + "digest": "DiywoRFzC33smQhVf5K7AcM853XFgfgFxBGErLTEvVWi", "effects": { "checkpoint": { "sequenceNumber": 2 @@ -290,32 +292,16 @@ Response: { } } -task 20, lines 174-196: -//# run-graphql --cursors {"c":4,"t":2,"i":false} +task 21, lines 212-235: +//# run-graphql --cursors {"c":4,"t":2,"i":true} Response: { "data": { "transactionBlocks": { "pageInfo": { - "hasNextPage": false, "hasPreviousPage": false, - "endCursor": null, - "startCursor": null - }, - "edges": [] - } - } -} - -task 21, lines 198-220: -//# run-graphql --cursors {"c":4,"t":0,"i":false} -Response: { - "data": { - "transactionBlocks": { - "pageInfo": { "hasNextPage": false, - "hasPreviousPage": false, - "endCursor": null, - "startCursor": null + "startCursor": null, + "endCursor": null }, "edges": [] } diff --git a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/last.move b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/last.move index 98f9e1f62446d..6a84f9eabe90b 100644 --- a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/last.move +++ b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/equal/last.move @@ -1,6 +1,8 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 +// Mirrors scan_limit/equal/first.move, paginating backwards where first and scanLimit are equal. + //# init --protocol-version 48 --addresses Test=0x0 --accounts A B --simulator //# publish @@ -28,9 +30,9 @@ module Test::M1 { //# create-checkpoint -//# run Test::M1::create --args 0 @A --sender A +//# run Test::M1::create --args 0 @B --sender A -//# run Test::M1::create --args 1 @A --sender A +//# run Test::M1::create --args 1 @B --sender A //# run Test::M1::create --args 2 @A --sender A @@ -40,33 +42,36 @@ module Test::M1 { //# create-checkpoint -//# run Test::M1::create --args 100 @A --sender A +//# run Test::M1::create --args 100 @B --sender A //# run Test::M1::create --args 101 @A --sender A -//# run Test::M1::create --args 102 @A --sender A +//# run Test::M1::create --args 102 @B --sender A //# run Test::M1::create --args 103 @A --sender A -//# run Test::M1::create --args 104 @A --sender A +//# run Test::M1::create --args 104 @B --sender A //# create-checkpoint //# run-graphql # Expect ten results { - transactionBlocks(last: 50 filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(last: 50 filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } - nodes { - digest - effects { - checkpoint { - sequenceNumber + edges { + cursor + node { + digest + effects { + checkpoint { + sequenceNumber + } } } } @@ -75,15 +80,16 @@ module Test::M1 { //# run-graphql -# With a scanLimit of 1, we should get a transaction whose digest corresponds to the last of the -# previous result, and `hasPrevPage` should be true +# boundary cursors are scan limited +# startCursor: 10, endCursor: 11 +# result is single element with cursor: 11 { - transactionBlocks(last: 1 scanLimit: 1 filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(last: 2 scanLimit: 2 filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } edges { cursor @@ -99,15 +105,17 @@ module Test::M1 { } } -//# run-graphql --cursors {"c":4,"t":11,"i":false} -# The query fetches the second to last transaction from the list of ten +//# run-graphql --cursors {"c":4,"t":10,"i":true} +# boundary cursors are scan limited +# startCursor: 9, endCursor: 9 +# result is single element with cursor: 9 { - transactionBlocks(last: 1 scanLimit: 1 before: "@{cursor_0}" filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(last: 1 scanLimit: 1 before: "@{cursor_0}" filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } edges { cursor @@ -123,15 +131,17 @@ module Test::M1 { } } -//# run-graphql --cursors {"c":4,"t":7,"i":false} -# The query fetches the fifth transaction from the set, also the last transaction from checkpoint 2 +//# run-graphql --cursors {"c":4,"t":9,"i":true} +# boundary cursors are scan limited +# startCursor: 6, endCursor: 8 +# result is single element with cursor: 7 { - transactionBlocks(last: 1 scanLimit: 1 before: "@{cursor_0}" filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(last: 3 scanLimit: 3 before: "@{cursor_0}" filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } edges { cursor @@ -147,15 +157,17 @@ module Test::M1 { } } -//# run-graphql --cursors {"c":4,"t":3,"i":false} -# Fetches the first transaction, hasPrevPage is false, hasNextPage is true +//# run-graphql --cursors {"c":4,"t":6,"i":true} +# boundary cursors are scan limited +# startCursor: 4, endCursor: 5 +# expect empty set { - transactionBlocks(last: 1 scanLimit: 1 before: "@{cursor_0}" filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(last: 2 scanLimit: 2 before: "@{cursor_0}" filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } edges { cursor @@ -171,15 +183,16 @@ module Test::M1 { } } -//# run-graphql --cursors {"c":4,"t":2,"i":false} -# Should yield no results, no cursors, and both pages are false +//# run-graphql --cursors {"c":4,"t":4,"i":true} +# Returns the first two matching transactions, boundary cursors both have `is_scan_limited: true` +# startCursor: 2, endCursor: 3 { - transactionBlocks(last: 1 scanLimit: 1 before: "@{cursor_0}" filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(last: 2 scanLimit: 2 before: "@{cursor_0}" filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } edges { cursor @@ -195,15 +208,17 @@ module Test::M1 { } } -//# run-graphql --cursors {"c":4,"t":0,"i":false} -# Should yield no results, no cursors, and both pages are false + +//# run-graphql --cursors {"c":4,"t":2,"i":true} +# Since we know from the previous query that there is not a previous page at this cursor, +# Expect false for page flags and null for cursors { - transactionBlocks(last: 1 scanLimit: 1 before: "@{cursor_0}" filter: {recvAddress: "@{A}" afterCheckpoint: 1 beforeCheckpoint: 4}) { + transactionBlocks(last: 2 scanLimit: 2 before: "@{cursor_0}" filter: {recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } edges { cursor diff --git a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/not_sure.exp b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/not_sure.exp deleted file mode 100644 index 77a10b7a55da5..0000000000000 --- a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/not_sure.exp +++ /dev/null @@ -1,331 +0,0 @@ -processed 24 tasks - -init: -A: object(0,0), B: object(0,1) - -task 1, lines 6-27: -//# publish -created: object(1,0) -mutated: object(0,2) -gas summary: computation_cost: 1000000, storage_cost: 5798800, storage_rebate: 0, non_refundable_storage_fee: 0 - -task 2, line 29: -//# create-checkpoint -Checkpoint created: 1 - -task 3, line 31: -//# run Test::M1::create --args 0 @A --sender A -created: object(3,0) -mutated: object(0,0) -gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 0, non_refundable_storage_fee: 0 - -task 4, line 33: -//# run Test::M1::create --args 1 @A --sender A -created: object(4,0) -mutated: object(0,0) -gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 - -task 5, line 35: -//# run Test::M1::create --args 2 @B --sender A -created: object(5,0) -mutated: object(0,0) -gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 - -task 6, line 37: -//# run Test::M1::create --args 3 @B --sender B -created: object(6,0) -mutated: object(0,1) -gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 0, non_refundable_storage_fee: 0 - -task 7, line 39: -//# run Test::M1::create --args 4 @B --sender B -created: object(7,0) -mutated: object(0,1) -gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 - -task 8, line 41: -//# create-checkpoint -Checkpoint created: 2 - -task 9, line 43: -//# run Test::M1::create --args 100 @B --sender B -created: object(9,0) -mutated: object(0,1) -gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 - -task 10, line 45: -//# run Test::M1::create --args 101 @B --sender B -created: object(10,0) -mutated: object(0,1) -gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 - -task 11, line 47: -//# run Test::M1::create --args 102 @B --sender A -created: object(11,0) -mutated: object(0,0) -gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 - -task 12, line 49: -//# run Test::M1::create --args 103 @B --sender A -created: object(12,0) -mutated: object(0,0) -gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 - -task 13, line 51: -//# run Test::M1::create --args 104 @B --sender A -created: object(13,0) -mutated: object(0,0) -gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 - -task 14, line 53: -//# create-checkpoint -Checkpoint created: 3 - -task 15, line 55: -//# run Test::M1::create --args 100 @B --sender B -created: object(15,0) -mutated: object(0,1) -gas summary: computation_cost: 1000000, storage_cost: 2302800, storage_rebate: 978120, non_refundable_storage_fee: 9880 - -task 16, line 57: -//# create-checkpoint -Checkpoint created: 4 - -task 17, lines 59-82: -//# run-graphql -Response: { - "data": { - "transactionBlocks": { - "pageInfo": { - "hasNextPage": true, - "hasPreviousPage": false, - "endCursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0", - "startCursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0" - }, - "edges": [ - { - "cursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0", - "node": { - "digest": "CReUjLynvpq4dD4w6zekGxvSyBBQF2e3KG3K2Rs7oD8L", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - } - } - ] - } - } -} - -task 18, lines 84-106: -//# run-graphql --cursors {"c":4,"t":2,"i":false} -Response: { - "data": { - "transactionBlocks": { - "pageInfo": { - "hasNextPage": true, - "hasPreviousPage": true, - "endCursor": "eyJjIjo0LCJ0IjozLCJpIjpmYWxzZX0", - "startCursor": "eyJjIjo0LCJ0IjozLCJpIjpmYWxzZX0" - }, - "edges": [ - { - "cursor": "eyJjIjo0LCJ0IjozLCJpIjpmYWxzZX0", - "node": { - "digest": "BB6bMUxrBJX9wANzzptKnJM3bMVFKnD4xtY8DGWthaH9", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - } - } - ] - } - } -} - -task 19, lines 108-129: -//# run-graphql --cursors {"c":4,"t":3,"i":false} -Response: { - "data": { - "transactionBlocks": { - "pageInfo": { - "hasNextPage": true, - "hasPreviousPage": false, - "endCursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0", - "startCursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0" - }, - "edges": [ - { - "cursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0", - "node": { - "digest": "CReUjLynvpq4dD4w6zekGxvSyBBQF2e3KG3K2Rs7oD8L", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - } - } - ] - } - } -} - -task 20, lines 131-156: -//# run-graphql --cursors {"c":4,"t":4,"i":false} -Response: { - "data": { - "transactionBlocks": { - "pageInfo": { - "hasNextPage": true, - "hasPreviousPage": false, - "endCursor": "eyJjIjo0LCJ0IjozLCJpIjpmYWxzZX0", - "startCursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0" - }, - "edges": [ - { - "cursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0", - "node": { - "digest": "CReUjLynvpq4dD4w6zekGxvSyBBQF2e3KG3K2Rs7oD8L", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - } - }, - { - "cursor": "eyJjIjo0LCJ0IjozLCJpIjpmYWxzZX0", - "node": { - "digest": "BB6bMUxrBJX9wANzzptKnJM3bMVFKnD4xtY8DGWthaH9", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - } - } - ] - } - } -} - -task 21, lines 158-182: -//# run-graphql -Response: { - "data": { - "transactionBlocks": { - "pageInfo": { - "hasNextPage": true, - "hasPreviousPage": false, - "endCursor": "eyJjIjo0LCJ0Ijo2LCJpIjp0cnVlfQ", - "startCursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0" - }, - "edges": [ - { - "cursor": "eyJjIjo0LCJ0IjoyLCJpIjpmYWxzZX0", - "node": { - "digest": "CReUjLynvpq4dD4w6zekGxvSyBBQF2e3KG3K2Rs7oD8L", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - } - }, - { - "cursor": "eyJjIjo0LCJ0IjozLCJpIjpmYWxzZX0", - "node": { - "digest": "BB6bMUxrBJX9wANzzptKnJM3bMVFKnD4xtY8DGWthaH9", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - } - }, - { - "cursor": "eyJjIjo0LCJ0Ijo0LCJpIjpmYWxzZX0", - "node": { - "digest": "BbHDa5U8CfAk95yFLTVTaeKwCAXhLrcpqEeG3T8z7Sii", - "effects": { - "checkpoint": { - "sequenceNumber": 2 - } - } - } - } - ] - } - } -} - -task 22, lines 184-208: -//# run-graphql --cursors {"c":4,"t":6,"i":true} -Response: { - "data": { - "transactionBlocks": { - "pageInfo": { - "hasNextPage": true, - "hasPreviousPage": true, - "endCursor": "eyJjIjo0LCJ0IjoxMSwiaSI6ZmFsc2V9", - "startCursor": "eyJjIjo0LCJ0Ijo3LCJpIjp0cnVlfQ" - }, - "edges": [ - { - "cursor": "eyJjIjo0LCJ0Ijo5LCJpIjpmYWxzZX0", - "node": { - "digest": "Bw31PqH9Z7W1PtaGAqPtvErMbTPZeeu5Ru3cXqCtDhns", - "effects": { - "checkpoint": { - "sequenceNumber": 3 - } - } - } - }, - { - "cursor": "eyJjIjo0LCJ0IjoxMCwiaSI6ZmFsc2V9", - "node": { - "digest": "AjdVaGXpAZmyhskAZKXzxk5zaMvaaMfmVDFVu6ApzBA9", - "effects": { - "checkpoint": { - "sequenceNumber": 3 - } - } - } - }, - { - "cursor": "eyJjIjo0LCJ0IjoxMSwiaSI6ZmFsc2V9", - "node": { - "digest": "8f9P48WkmU8jQchKFeC6dM9WCeibp5JKdPkzJVrSGtfN", - "effects": { - "checkpoint": { - "sequenceNumber": 3 - } - } - } - } - ] - } - } -} - -task 23, lines 211-234: -//# run-graphql --cursors {"c":4,"t":11,"i":false} -Response: { - "data": { - "transactionBlocks": { - "pageInfo": { - "hasNextPage": false, - "hasPreviousPage": true, - "endCursor": null, - "startCursor": "eyJjIjo0LCJ0IjoxMiwiaSI6dHJ1ZX0" - }, - "edges": [] - } - } -} diff --git a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/not_sure.move b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/not_sure.move deleted file mode 100644 index df628c650ab89..0000000000000 --- a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/not_sure.move +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -//# init --protocol-version 48 --addresses Test=0x0 --accounts A B --simulator - -//# publish -module Test::M1 { - public struct Object has key, store { - id: UID, - value: u64, - } - - public entry fun create(value: u64, recipient: address, ctx: &mut TxContext) { - transfer::public_transfer( - Object { id: object::new(ctx), value }, - recipient - ) - } - - public fun swap_value_and_send(mut lhs: Object, mut rhs: Object, recipient: address) { - let tmp = lhs.value; - lhs.value = rhs.value; - rhs.value = tmp; - transfer::public_transfer(lhs, recipient); - transfer::public_transfer(rhs, recipient); - } -} - -//# create-checkpoint - -//# run Test::M1::create --args 0 @A --sender A - -//# run Test::M1::create --args 1 @A --sender A - -//# run Test::M1::create --args 2 @B --sender A - -//# run Test::M1::create --args 3 @B --sender B - -//# run Test::M1::create --args 4 @B --sender B - -//# create-checkpoint - -//# run Test::M1::create --args 100 @B --sender B - -//# run Test::M1::create --args 101 @B --sender B - -//# run Test::M1::create --args 102 @B --sender A - -//# run Test::M1::create --args 103 @B --sender A - -//# run Test::M1::create --args 104 @B --sender A - -//# create-checkpoint - -//# run Test::M1::create --args 100 @B --sender B - -//# create-checkpoint - -//# run-graphql -# Test normal pagination behavior. Initial fetch should yield `startCursor` = `endCursor`. -# `hasNextPage` is true and `hasPreviousPage` is false -{ - transactionBlocks(first: 50 scanLimit: 1 filter: {signAddress: "@{A}" afterCheckpoint: 1}) { - pageInfo { - hasNextPage - hasPreviousPage - endCursor - startCursor - } - edges { - cursor - node { - digest - effects { - checkpoint { - sequenceNumber - } - } - } - } - } -} - -//# run-graphql --cursors {"c":4,"t":2,"i":false} -# `startCursor` = `endCursor`, both `hasNextPage` and `hasPreviousPage` are true -{ - transactionBlocks(first: 50 scanLimit: 1 after: "@{cursor_0}" filter: {signAddress: "@{A}" afterCheckpoint: 1}) { - pageInfo { - hasNextPage - hasPreviousPage - endCursor - startCursor - } - edges { - cursor - node { - digest - effects { - checkpoint { - sequenceNumber - } - } - } - } - } -} - -//# run-graphql --cursors {"c":4,"t":3,"i":false} -{ - transactionBlocks(first: 50 scanLimit: 1 before: "@{cursor_0}" filter: {signAddress: "@{A}" afterCheckpoint: 1}) { - pageInfo { - hasNextPage - hasPreviousPage - endCursor - startCursor - } - edges { - cursor - node { - digest - effects { - checkpoint { - sequenceNumber - } - } - } - } - } -} - -//# run-graphql --cursors {"c":4,"t":4,"i":false} -# `scanLimit` exceeds the position of the `before` cursor. -# Expect the endCursor to be at t:3 and `hasNextPage` to be true. -# The `endCursor` should not indicate that it comes from `scanLimit`. -# In other words, don't overwrite the behavior of default `paginate_results` -{ - transactionBlocks(first: 50 scanLimit: 10 before: "@{cursor_0}" filter: {signAddress: "@{A}" afterCheckpoint: 1}) { - pageInfo { - hasNextPage - hasPreviousPage - endCursor - startCursor - } - edges { - cursor - node { - digest - effects { - checkpoint { - sequenceNumber - } - } - } - } - } -} - -//# run-graphql -# Of the first 6 transactions to scan, only the first three will match. -# The `endCursor` should be overriden to point to t:6, and `hasNextPage` should be true. -# Additionally, the `endCursor` should decode to indicate it is from `scanLimit` -{ - transactionBlocks(first: 50 scanLimit: 5 filter: {signAddress: "@{A}" afterCheckpoint: 1}) { - pageInfo { - hasNextPage - hasPreviousPage - endCursor - startCursor - } - edges { - cursor - node { - digest - effects { - checkpoint { - sequenceNumber - } - } - } - } - } -} - -//# run-graphql --cursors {"c":4,"t":6,"i":true} -# The `startCursor` should be influenced by the `after` cursor, and have t:7. -# At the same time, t:7 should not actually show up in the result set - the next match is at t:9. -# The `endCursor` should come from the last transaction, and it should not indicate that it came from `scanLimit`. -{ - transactionBlocks(first: 50 scanLimit: 5 after: "@{cursor_0}" filter: {signAddress: "@{A}" afterCheckpoint: 1}) { - pageInfo { - hasNextPage - hasPreviousPage - endCursor - startCursor - } - edges { - cursor - node { - digest - effects { - checkpoint { - sequenceNumber - } - } - } - } - } -} - - -//# run-graphql --cursors {"c":4,"t":11,"i":false} -# no next page and thus no `endCursor`. -# `startCursor` is at t:12 and should be from `scanLimit` -{ - transactionBlocks(first: 50 scanLimit: 5 after: "@{cursor_0}" filter: {signAddress: "@{A}" afterCheckpoint: 1}) { - pageInfo { - hasNextPage - hasPreviousPage - endCursor - startCursor - } - edges { - cursor - node { - digest - effects { - checkpoint { - sequenceNumber - } - } - } - } - } -} diff --git a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/require.exp b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/require.exp index 36e8fbb400220..1e5207ad10ed9 100644 --- a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/require.exp +++ b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/require.exp @@ -306,8 +306,8 @@ Response: { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, - "endCursor": "eyJjIjozLCJ0IjoxMSwiaSI6ZmFsc2V9", - "startCursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0" + "endCursor": "eyJjIjozLCJ0IjoxMSwiaSI6dHJ1ZX0", + "startCursor": "eyJjIjozLCJ0IjoyLCJpIjp0cnVlfQ" }, "nodes": [ { @@ -426,8 +426,8 @@ Response: { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, - "endCursor": "eyJjIjozLCJ0IjoxMSwiaSI6ZmFsc2V9", - "startCursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0" + "endCursor": "eyJjIjozLCJ0IjoxMSwiaSI6dHJ1ZX0", + "startCursor": "eyJjIjozLCJ0IjoyLCJpIjp0cnVlfQ" }, "nodes": [ { @@ -546,8 +546,8 @@ Response: { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, - "endCursor": null, - "startCursor": null + "endCursor": "eyJjIjozLCJ0IjoxMSwiaSI6dHJ1ZX0", + "startCursor": "eyJjIjozLCJ0IjoyLCJpIjp0cnVlfQ" }, "nodes": [] } @@ -577,23 +577,26 @@ Response: { ] } -task 24, lines 245-264: +task 24, lines 245-269: //# run-graphql Response: { "data": { "transactionBlocks": { "pageInfo": { - "hasNextPage": false, "hasPreviousPage": false, - "endCursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0", - "startCursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0" + "hasNextPage": false, + "startCursor": "eyJjIjozLCJ0IjoyLCJpIjp0cnVlfQ", + "endCursor": "eyJjIjozLCJ0IjoxMSwiaSI6dHJ1ZX0" }, - "nodes": [ - { - "digest": "HzyC8gcn4m1ymKxYSpWMaNnmbrqm4hX7UBteJ4me3LFd", - "effects": { - "checkpoint": { - "sequenceNumber": 2 + "edges": [ + { + "cursor": "eyJjIjozLCJ0IjoyLCJpIjpmYWxzZX0", + "node": { + "digest": "HzyC8gcn4m1ymKxYSpWMaNnmbrqm4hX7UBteJ4me3LFd", + "effects": { + "checkpoint": { + "sequenceNumber": 2 + } } } } diff --git a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/require.move b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/require.move index 3d95dfbce9769..90b5570b7ded3 100644 --- a/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/require.move +++ b/crates/sui-graphql-e2e-tests/tests/transactions/scan_limit/require.move @@ -243,20 +243,25 @@ module Test::M1 { } //# run-graphql -# valid +# Only one of the transactions will match this filter +# Because scanLimit is specified, the boundary cursors should be at 2 and 11, +# and both will indicate is_scan_limited { transactionBlocks(scanLimit: 50 filter: {signAddress: "@{A}" recvAddress: "@{B}" afterCheckpoint: 1 beforeCheckpoint: 4 changedObject: "@{obj_3_0}"}) { pageInfo { - hasNextPage hasPreviousPage - endCursor + hasNextPage startCursor + endCursor } - nodes { - digest - effects { - checkpoint { - sequenceNumber + edges { + cursor + node { + digest + effects { + checkpoint { + sequenceNumber + } } } }