diff --git a/rpcs/openapi.yaml b/rpcs/openapi.yaml index 4ddddf3..2782f3c 100644 --- a/rpcs/openapi.yaml +++ b/rpcs/openapi.yaml @@ -100,6 +100,8 @@ paths: $ref: './transaction/EXPERIMENTAL_tx_status.yaml#/paths/~1' /EXPERIMENTAL_receipt: $ref: './transaction/EXPERIMENTAL_receipt.yaml#/paths/~1' + /EXPERIMENTAL_receipt_to_tx: + $ref: './transaction/EXPERIMENTAL_receipt_to_tx.yaml#/paths/~1' # Validator operations /validators_current: diff --git a/rpcs/transaction/EXPERIMENTAL_receipt_to_tx.yaml b/rpcs/transaction/EXPERIMENTAL_receipt_to_tx.yaml new file mode 100644 index 0000000..ac0bdb0 --- /dev/null +++ b/rpcs/transaction/EXPERIMENTAL_receipt_to_tx.yaml @@ -0,0 +1,119 @@ +openapi: 3.1.0 +info: + title: "NEAR Protocol RPC: Resolve receipt to transaction" + description: "Resolve a receipt ID to the transaction hash and signer that produced it. Requires a node with `save_receipt_to_tx` enabled; unindexed receipts return `UNKNOWN_RECEIPT`." + version: 1.0.0 +servers: + - url: "https://rpc.mainnet.fastnear.com" + description: Mainnet + - url: "https://rpc.testnet.fastnear.com" + description: Testnet +paths: + /: + post: + operationId: EXPERIMENTAL_receipt_to_tx + summary: Resolve receipt to transaction + description: "Resolve a receipt ID to the transaction hash and signer that produced it. Requires a node with `save_receipt_to_tx` enabled; unindexed receipts return `UNKNOWN_RECEIPT`." + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [jsonrpc, id, method, params] + properties: + jsonrpc: + type: string + enum: ["2.0"] + id: + type: string + example: fastnear + method: + type: string + enum: [EXPERIMENTAL_receipt_to_tx] + params: + type: object + properties: + block_height: + type: [integer, "null"] + description: "Optional hint: block height near where the receipt was created, to bound the fallback scan." + format: uint64 + minimum: 0 + receipt_id: + type: string + description: Base58-encoded receipt ID to resolve to its originating transaction. + shard_id: + type: [integer, "null"] + description: "Optional hint: shard to scan at the hint height; omit to scan all tracked shards." + window: + type: [integer, "null"] + description: "Optional hint: ± block-height window scanned around the hint before walking ancestor blocks." + format: uint64 + minimum: 0 + required: [receipt_id] + examples: + mainnet: + summary: Resolve receipt to transaction (Mainnet) + value: + jsonrpc: "2.0" + id: fastnear + method: EXPERIMENTAL_receipt_to_tx + params: + receipt_id: FcFKrKQziMPCgYMFiLMZwecBtA7vqxdkatkhc1j3GYj8 + testnet: + summary: Resolve receipt to transaction (Testnet) + value: + jsonrpc: "2.0" + id: fastnear + method: EXPERIMENTAL_receipt_to_tx + params: + block_height: null + receipt_id: ExampleReceiptId + shard_id: 0 + window: null + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: "#/components/schemas/JsonRpcResponse" +security: + - ApiKeyAuth: [] +components: + securitySchemes: + ApiKeyAuth: + type: apiKey + in: query + name: apiKey + schemas: + JsonRpcResponse: + type: object + required: [jsonrpc, id] + properties: + jsonrpc: + type: string + enum: ["2.0"] + id: + oneOf: + - type: string + - type: number + result: + type: object + properties: + sender_account_id: + type: string + description: NEAR account ID + transaction_hash: + type: string + description: Base58-encoded hash + required: [transaction_hash, sender_account_id] + error: + type: object + properties: + code: + type: integer + message: + type: string + data: + type: object diff --git a/scripts/audit-page-model-routes.js b/scripts/audit-page-model-routes.js index cea9feb..038b4e3 100644 --- a/scripts/audit-page-model-routes.js +++ b/scripts/audit-page-model-routes.js @@ -11,7 +11,7 @@ const EXPECTED_FAMILY_COUNTS = { "rpcs/block": 3, "rpcs/contract": 5, "rpcs/protocol": 20, - "rpcs/transaction": 6, + "rpcs/transaction": 7, "rpcs/validators": 3, "apis/fastnear": 14, "apis/kv-fastdata": 9, diff --git a/scripts/nearcore-operation-map.js b/scripts/nearcore-operation-map.js index 646ba95..f1e2080 100644 --- a/scripts/nearcore-operation-map.js +++ b/scripts/nearcore-operation-map.js @@ -578,6 +578,28 @@ const OPERATIONS = [ }, }, }, + { + type: 'simple', + nearcorePath: '/EXPERIMENTAL_receipt_to_tx', + file: 'transaction/EXPERIMENTAL_receipt_to_tx.yaml', + category: 'transaction', + operationId: 'EXPERIMENTAL_receipt_to_tx', + summary: 'Resolve receipt to transaction', + description: "Resolve a receipt ID to the transaction hash and signer that produced it. Requires a node with `save_receipt_to_tx` enabled; unindexed receipts return `UNKNOWN_RECEIPT`.", + fieldDescriptions: { + request: { + receipt_id: 'Base58-encoded receipt ID to resolve to its originating transaction.', + block_height: 'Optional hint: block height near where the receipt was created, to bound the fallback scan.', + shard_id: 'Optional hint: shard to scan at the hint height; omit to scan all tracked shards.', + window: 'Optional hint: ± block-height window scanned around the hint before walking ancestor blocks.', + }, + }, + exampleParamsByNetwork: { + mainnet: { + receipt_id: 'FcFKrKQziMPCgYMFiLMZwecBtA7vqxdkatkhc1j3GYj8', + }, + }, + }, { type: 'simple', nearcorePath: '/EXPERIMENTAL_protocol_config', diff --git a/scripts/rpc-example-config.js b/scripts/rpc-example-config.js index 633d371..4476122 100644 --- a/scripts/rpc-example-config.js +++ b/scripts/rpc-example-config.js @@ -114,7 +114,19 @@ const CURATED_RPC_EXAMPLE_PARAMS = { }, }; -const ALLOWED_RPC_PLACEHOLDERS = {}; +const ALLOWED_RPC_PLACEHOLDERS = { + // No curated testnet receipt yet; mainnet uses a real receipt id. Allow the + // generated placeholder on testnet until a real, index-resolvable testnet + // example is curated. + EXPERIMENTAL_receipt_to_tx: { + testnet: { + receipt_id: { + value: 'ExampleReceiptId', + reason: 'No curated testnet receipt yet; mainnet uses a real receipt id.', + }, + }, + }, +}; const MANUAL_RPC_EXAMPLE_OVERRIDES = { EXPERIMENTAL_protocol_config: { @@ -159,7 +171,21 @@ const MANUAL_RPC_EXAMPLE_OVERRIDES = { }, }; -const AUDIT_SKIPS = {}; +const AUDIT_SKIPS = { + // receipt→tx resolution needs a save_receipt_to_tx-enabled node with the + // receipt still indexed; the public RPC returns UNKNOWN_RECEIPT otherwise, so + // the example is representative-only and excluded from the live audit. + EXPERIMENTAL_receipt_to_tx: { + mainnet: { + skip: true, + reason: 'Requires a save_receipt_to_tx-enabled node with the receipt indexed; returns UNKNOWN_RECEIPT otherwise.', + }, + testnet: { + skip: true, + reason: 'Requires a save_receipt_to_tx-enabled node with the receipt indexed; returns UNKNOWN_RECEIPT otherwise.', + }, + }, +}; function cloneJson(value) { if (value === undefined) { diff --git a/scripts/structured-graph-common.js b/scripts/structured-graph-common.js index eebe73e..768ffb5 100644 --- a/scripts/structured-graph-common.js +++ b/scripts/structured-graph-common.js @@ -131,7 +131,7 @@ const EXPECTED_FAMILY_OPERATION_COUNTS = { "rpc-block": 3, "rpc-contract": 5, "rpc-protocol": 20, - "rpc-transaction": 6, + "rpc-transaction": 7, "rpc-validators": 3, }; diff --git a/shared/generatedFastnearPageModels.json b/shared/generatedFastnearPageModels.json index 64f8eef..fb9d630 100644 --- a/shared/generatedFastnearPageModels.json +++ b/shared/generatedFastnearPageModels.json @@ -11883,6 +11883,353 @@ ], "sourceSpec": "rpcs/transaction/EXPERIMENTAL_receipt.yaml" }, + { + "canonicalPath": "/rpcs/transaction/EXPERIMENTAL_receipt_to_tx", + "info": { + "description": "Resolve a receipt ID to the transaction hash and signer that produced it. Requires a node with `save_receipt_to_tx` enabled; unindexed receipts return `UNKNOWN_RECEIPT`.", + "operationId": "EXPERIMENTAL_receipt_to_tx", + "summary": "Resolve receipt to transaction", + "title": "NEAR Protocol RPC: Resolve receipt to transaction", + "version": "1.0.0" + }, + "interaction": { + "authTransport": "bearer", + "defaultId": "fastnear", + "fields": [ + { + "description": "Optional hint: block height near where the receipt was created, to bound the fallback scan.", + "label": "Block Height", + "location": "body", + "name": "block_height", + "required": false, + "schema": { + "type": "integer", + "nullable": true, + "description": "Optional hint: block height near where the receipt was created, to bound the fallback scan.", + "format": "uint64" + } + }, + { + "description": "Base58-encoded receipt ID to resolve to its originating transaction.", + "label": "Receipt Id", + "location": "body", + "name": "receipt_id", + "required": true, + "schema": { + "type": "string", + "description": "Base58-encoded receipt ID to resolve to its originating transaction." + } + }, + { + "description": "Optional hint: shard to scan at the hint height; omit to scan all tracked shards.", + "label": "Shard Id", + "location": "body", + "name": "shard_id", + "required": false, + "schema": { + "type": "integer", + "nullable": true, + "description": "Optional hint: shard to scan at the hint height; omit to scan all tracked shards." + } + }, + { + "description": "Optional hint: ± block-height window scanned around the hint before walking ancestor blocks.", + "label": "Window", + "location": "body", + "name": "window", + "required": false, + "schema": { + "type": "integer", + "nullable": true, + "description": "Optional hint: ± block-height window scanned around the hint before walking ancestor blocks.", + "format": "uint64" + } + } + ], + "kind": "rpc-EXPERIMENTAL-receipt-to-tx", + "networks": [ + { + "defaultFields": { + "receipt_id": "FcFKrKQziMPCgYMFiLMZwecBtA7vqxdkatkhc1j3GYj8" + }, + "key": "mainnet", + "label": "Mainnet", + "url": "https://rpc.mainnet.fastnear.com" + }, + { + "defaultFields": { + "receipt_id": "ExampleReceiptId", + "shard_id": 0 + }, + "key": "testnet", + "label": "Testnet", + "url": "https://rpc.testnet.fastnear.com" + } + ], + "requestMethod": "EXPERIMENTAL_receipt_to_tx", + "supportsFinality": false, + "transport": "json-rpc" + }, + "pageModelId": "rpc-EXPERIMENTAL-receipt-to-tx", + "replaceOperationPage": true, + "request": { + "bodySchema": { + "type": "object", + "required": [ + "jsonrpc", + "id", + "method", + "params" + ], + "properties": [ + { + "name": "jsonrpc", + "required": true, + "schema": { + "type": "string", + "enum": [ + "2.0" + ] + } + }, + { + "name": "id", + "required": true, + "schema": { + "type": "string", + "example": "fastnear" + } + }, + { + "name": "method", + "required": true, + "schema": { + "type": "string", + "enum": [ + "EXPERIMENTAL_receipt_to_tx" + ] + } + }, + { + "name": "params", + "required": true, + "schema": { + "type": "object", + "required": [ + "receipt_id" + ], + "properties": [ + { + "name": "block_height", + "required": false, + "schema": { + "type": "integer", + "nullable": true, + "description": "Optional hint: block height near where the receipt was created, to bound the fallback scan.", + "format": "uint64" + } + }, + { + "name": "receipt_id", + "required": true, + "schema": { + "type": "string", + "description": "Base58-encoded receipt ID to resolve to its originating transaction." + } + }, + { + "name": "shard_id", + "required": false, + "schema": { + "type": "integer", + "nullable": true, + "description": "Optional hint: shard to scan at the hint height; omit to scan all tracked shards." + } + }, + { + "name": "window", + "required": false, + "schema": { + "type": "integer", + "nullable": true, + "description": "Optional hint: ± block-height window scanned around the hint before walking ancestor blocks.", + "format": "uint64" + } + } + ] + } + } + ] + }, + "examples": [ + { + "id": "mainnet", + "label": "Resolve receipt to transaction (Mainnet)", + "network": "mainnet", + "request": { + "body": { + "jsonrpc": "2.0", + "id": "fastnear", + "method": "EXPERIMENTAL_receipt_to_tx", + "params": { + "receipt_id": "FcFKrKQziMPCgYMFiLMZwecBtA7vqxdkatkhc1j3GYj8" + } + }, + "headers": {}, + "path": {}, + "query": {} + } + }, + { + "id": "testnet", + "label": "Resolve receipt to transaction (Testnet)", + "network": "testnet", + "request": { + "body": { + "jsonrpc": "2.0", + "id": "fastnear", + "method": "EXPERIMENTAL_receipt_to_tx", + "params": { + "block_height": null, + "receipt_id": "ExampleReceiptId", + "shard_id": 0, + "window": null + } + }, + "headers": {}, + "path": {}, + "query": {} + } + } + ], + "mediaType": "application/json", + "parameters": { + "header": [], + "path": [], + "query": [] + }, + "required": true + }, + "responses": [ + { + "description": "Successful response", + "mediaType": "application/json", + "schema": { + "type": "object", + "required": [ + "jsonrpc", + "id" + ], + "properties": [ + { + "name": "jsonrpc", + "required": true, + "schema": { + "type": "string", + "enum": [ + "2.0" + ] + } + }, + { + "name": "id", + "required": true, + "schema": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + { + "name": "result", + "required": false, + "schema": { + "type": "object", + "required": [ + "transaction_hash", + "sender_account_id" + ], + "properties": [ + { + "name": "sender_account_id", + "required": true, + "schema": { + "type": "string", + "description": "NEAR account ID" + } + }, + { + "name": "transaction_hash", + "required": true, + "schema": { + "type": "string", + "description": "Base58-encoded hash" + } + } + ] + } + }, + { + "name": "error", + "required": false, + "schema": { + "type": "object", + "properties": [ + { + "name": "code", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "message", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "data", + "required": false, + "schema": { + "type": "object" + } + } + ] + } + } + ], + "refName": "JsonRpcResponse" + }, + "status": "200" + } + ], + "route": { + "method": "POST", + "path": "/", + "transport": "json-rpc" + }, + "routeAliases": [ + "/rpcs/transaction/EXPERIMENTAL_receipt_to_tx/other/EXPERIMENTAL_receipt_to_tx", + "/reference/operation/EXPERIMENTAL_receipt_to_tx" + ], + "securitySchemes": [ + { + "description": "The OpenAPI contract describes the FastNEAR API key as a query parameter named apiKey.", + "id": "ApiKeyAuth", + "in": "query", + "name": "apiKey", + "type": "apiKey" + } + ], + "sourceSpec": "rpcs/transaction/EXPERIMENTAL_receipt_to_tx.yaml" + }, { "canonicalPath": "/rpcs/transaction/EXPERIMENTAL_tx_status", "info": { diff --git a/shared/generatedFastnearStructuredGraph.json b/shared/generatedFastnearStructuredGraph.json index db664da..225eab2 100644 --- a/shared/generatedFastnearStructuredGraph.json +++ b/shared/generatedFastnearStructuredGraph.json @@ -1008,6 +1008,20 @@ ], "pageModelId": "rpc-EXPERIMENTAL-receipt" }, + { + "canonicalPath": "/rpcs/transaction/EXPERIMENTAL_receipt_to_tx", + "items": [ + { + "label": "Transaction RPC", + "path": "/rpc" + }, + { + "label": "Resolve receipt to transaction", + "path": "/rpcs/transaction/EXPERIMENTAL_receipt_to_tx" + } + ], + "pageModelId": "rpc-EXPERIMENTAL-receipt-to-tx" + }, { "canonicalPath": "/rpcs/transaction/EXPERIMENTAL_tx_status", "items": [ @@ -1210,7 +1224,7 @@ "branch": "HEAD", "commitSha": "499283a5e3a6f8ea52bc068c28e3a7bebb1e38c0", "dirty": true, - "generatedAt": "2026-07-14T21:45:20.697Z", + "generatedAt": "2026-07-15T15:19:36.945Z", "releaseUrl": "https://github.com/near/nearcore/releases/tag/2.13.0", "repoRoot": "../nearcore", "repoUrl": "https://github.com/near/nearcore", @@ -3127,6 +3141,33 @@ "summary": "Get receipt by ID", "transport": "json-rpc" }, + { + "authSummary": "API key via query apiKey", + "canonicalPath": "/rpcs/transaction/EXPERIMENTAL_receipt_to_tx", + "description": "Resolve a receipt ID to the transaction hash and signer that produced it. Requires a node with `save_receipt_to_tx` enabled; unindexed receipts return `UNKNOWN_RECEIPT`.", + "docsPath": "/rpc/transaction/experimental-receipt-to-tx", + "familyId": "rpc-transaction", + "headline": "NEAR Protocol RPC: Resolve receipt to transaction", + "httpMethod": "POST", + "id": "rpc-EXPERIMENTAL-receipt-to-tx", + "name": "NEAR Protocol RPC: Resolve receipt to transaction", + "networkKeys": [ + "mainnet", + "testnet" + ], + "operationId": "EXPERIMENTAL_receipt_to_tx", + "pageModelId": "rpc-EXPERIMENTAL-receipt-to-tx", + "requestPath": "/", + "requestType": null, + "routeAliases": [ + "/rpcs/transaction/EXPERIMENTAL_receipt_to_tx/other/EXPERIMENTAL_receipt_to_tx", + "/reference/operation/EXPERIMENTAL_receipt_to_tx" + ], + "schemaType": "APIReference", + "sourceSpec": "rpcs/transaction/EXPERIMENTAL_receipt_to_tx.yaml", + "summary": "Resolve receipt to transaction", + "transport": "json-rpc" + }, { "authSummary": "API key via query apiKey", "canonicalPath": "/rpcs/transaction/EXPERIMENTAL_tx_status",