pull in latest upstream - #2
Open
TtheBC01 wants to merge 825 commits into
Open
Conversation
* add batch-settlement blog post * add img
* Create TSC.md Create TSC.md outlining the technical steering committee members as outlined by the x402 foundation charter. * Fix spelling --------- Co-authored-by: Erik <erikreppel@gmail.com>
* Add escrow scheme specification Introduces the `escrow` scheme for x402, built on Base's Commerce Payments Protocol. Supports two settlement paths: authorize (funds held in escrow) and charge (direct to receiver), both refundable post-settlement. Refs: #834, #1011 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Address review feedback on escrow scheme specs - Generalize scheme_escrow.md to be network-agnostic - Tighten verification: strict amount equality, tokenCollector recipient check, settlement simulation - Add error codes section and assetTransferMethod note - Simplify nonce derivation explanation * Rename scheme to commerce and align spec with implementation - Rename escrow → commerce per reviewer feedback - Add expiry fields to PaymentRequirements example - Align expiry field descriptions and example values Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * spec: rename escrow/commerce scheme to authCapture, add EVM payload schema Renames the scheme directory from commerce/ to authCapture/ and rewrites the EVM spec to cover both ERC-3009 and Permit2 payment-collector paths. Key spec additions: - extra field schema (captureAuthorizer, captureDeadline, refundDeadline, feeRecipient, min/maxFeeBps, autoCapture, assetTransferMethod) - Wire format + EIP-712 derivation tables for ERC-3009 and Permit2 - Spec -> on-chain PaymentInfo field mapping (preserves canonical Solidity names so EIP-712 typehash matches the AuthCaptureEscrow contract) - Universal contract addresses block (CREATE2-deterministic) - Verification step list aligned with facilitator implementation: preApprovalExpiry <= captureDeadline <= refundDeadline (>= allowed, matching contract _validatePayment) * spec: use canonical base/commerce-payments addresses Defer to the live deployment from base/commerce-payments@v1.0.0 instead of redeploying via CREATE2. Drop the now-obsolete inline address tables and salt-scheme paragraph; the Canonical Addresses annex now links to the upstream release notes (and Uniswap deployments docs for Permit2), matching scheme_exact_evm.md's third-party 'Canonical Permit2' annex pattern. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…2278) The Permit2 erc20-approval client was hardcoding 1_000_000_000 / 100_000_000 as gas fee fallbacks. TypeScript already exposes these as DEFAULT_MAX_FEE_PER_GAS / DEFAULT_MAX_PRIORITY_FEE_PER_GAS in evm/constants; add the matching Python constants and use them. No behavior change. Also adds the first unit tests for sign_erc20_approval_transaction covering the fallback and successful estimate paths.
* add --ignore-scripts * update to pnpm 11 and node 22 * align dep * fix axios headers * pin workflow actions * fix paywall * remove cache from publishing * add hedera publishing * remove e2e workflow * increase minminimumReleaseAge to 3days
* fix uv build * exclude-newer = 3 days
…d fix two→three typo (#2044) The exact-EVM scheme spec documented the extra object only by example, leaving readers unable to tell which fields are required vs conditional vs optional for each of the three asset transfer methods (eip3009, permit2, erc7710). Per-method classification is authoritative in the code but was not documented in the spec. Adds three field-definition blocks (one per assetTransferMethod) after each method's PAYMENT-SIGNATURE example, classifying: - extra.assetTransferMethod - extra.name - extra.version Classification per method: - eip3009: name and version are REQUIRED (needed for transferWithAuthorization signature construction). - permit2: name and version are CONDITIONAL (required when the token supports EIP-2612 for gasless Permit2 approval). - erc7710: name and version are OPTIONAL (not used by delegation- based transfers). Also fixes a stale count: 'one of two asset transfer methods' → 'one of three', since erc7710 was added without updating the summary sentence. Pure documentation. No new fields. No code changes.
…D 181228) support with USDC.e (#2309) Add USDC.e (Bridged USDC) as the default stablecoin for HPP mainnet (chain ID 190415) and HPP Sepolia (chain ID 181228) across all three SDKs: - TypeScript: DEFAULT_STABLECOINS map in @x402/evm + regenerated NETWORK_DECIMALS in @x402/paywall - Go: ChainIDHPP / ChainIDHPPSepolia constants, NetworkConfigs entries - Python: NETWORK_CONFIGS dict in x402.mechanisms.evm Contract details (verified on-chain): - Token: USDC.e (Bridged USDC, FiatTokenV2_2) - Address: 0x401eCb1D350407f13ba348573E5630B83638E30D (identical on both networks) - EIP-712 domain: name="Bridged USDC", version="2" - Decimals: 6 - EIP-3009: transferWithAuthorization supported Chain details: - HPP is an Arbitrum Orbit L2 operated by the HPP team - Mainnet (190415): https://mainnet.hpp.io | Explorer: https://explorer.hpp.io - Sepolia (181228): https://sepolia.hpp.io | Explorer: https://sepolia-explorer.hpp.io - Portal: https://portal.hpp.io USDC.e is the official bridged USDC issued by HPP, submitted by the HPP chain team (chain-endorsed asset per DEFAULT_ASSETS.md).
Generated-By: mintlify-agent Mintlify-Source: dashboard-editor Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
* Fix: invoke lifecycle hooks in payment payload creation * fix: invoke lifecycle hooks with correct context types in V1 and V2 * fix: suppress unhandled hook errors to satisfy errcheck linter * fix: handle hook errors and recovery on payment creation failure
* spec: added reference spec * feat: added x402BatchSettlement contract * feat: added tests * feat: mining 0x4020...0003 vanity & deploy to base sepolia * feat: updaded spec/contract per recommendations * feat: updated tests * feat: update x402BatchSettlement * feat: add peripheral contracts * feat: updated spec * feat: updated tests and deploy * feat: removed extra.receiver from spec * spec v1.2 (#44) * feat: added 4th deposit; renamed others * feat: updated tests * feat: add collectors model * feat: removed periphery contracts * feat: rename cooperativeWithdraw to refund * feat: added multicall to x402BatchSettlement for migration support * feat: added multichannel & migration test scenarios * feat: add deploy for peripery contracts * feat: pr feedback * feat: pr review feedback * feat: update settlement tye from address to x402BatchSettlement * feat: generate EIP3009 nonces from channelId & salt * feat: removed DOS vector for withdrawals * feat: deduplicate token/amount from permit2 call data * feat: using ReentrancyGuardTransient over ReetrancyGuard for gas efficiency * feat: added comment regarding unsupported tokens * feat: added nonces to refund signature * feat: updated CLAIM_BATCH_TYPEHASH to use full EIP-712 nested types * feat: merge Permit2DepositCollector's into one contract * feat: gate finalizeWithdraw to payer/payerAuthorizer * feat: added partial refunds * feat: updated spec * fix: unit tests & format * feat: revert settlement address from x402BatchSettlement to address type * feat: pr feedback * feat: pr feedback * chore: format * feat: deployed new contracts * feat: final PR reviews + styling doc * feat: pr feedback * feat: re-mine salts * fix: refunds could grief withdrawals * fix: a signature replay attach with refund nonces * fix: add balance check at initiateWithdraw time * fix: removed duplicate code for type hash getters * fix: avoid cross-chain channelId overlap * feat: remine & redeploy contracts to testnet * chore: move deposit events to after balance checks * feat: add nonReentrant modifier to initiateWithdraw * feat: add ChannelClosed event when balance returns to 0 with 0 claims * doc: natspec note for getClaimBatchDigest called with empty array * feat: added gas tests for x402BatchSettlement * feat: removed unused caller param from IDepositCollector.collect * feat: 100% test coverage for batch settlement across branches/functions/statemments/lines * chore: removed batch settlement spec * doc: document claim/finalizeWithdraw details and add x402-batch-settlement-implementers.md * feat: fix Permit2DepositCollector typehash * feat: documenting refund nonce behavior * feat: remine & deploy batch settlement contracts * chore: add audit reports * feat: deployed to base, polygon, arbitrum, world and world-chain * feat: removed old spec --------- Co-authored-by: phdargen <pdargent@icloud.com>
* fix paywall regen for new chains * changeset * fix format * fix paywall
* improve extension readmes * Add extension hook adapters for client and HTTP flows * Make SIWX extension self-register hooks * changeset
* limit s array size * go/py * add changeset * fix fmt
* Update docs/extensions/builder-code.mdx Generated-By: mintlify-agent Mintlify-Source: dashboard-editor * Update docs/extensions/builder-code.mdx Generated-By: mintlify-agent Mintlify-Source: dashboard-editor --------- Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
* fix(python): preserve streaming bodies on payment retry Buffer request content before the initial send so a 402 retry replays the same body. * chore(python): use pull request number for changelog
* docs(svm): add `upto` SVM scheme specification SVM profile of the network-agnostic `upto` scheme: a single-authorization payment channel whose escrow deposit is the ceiling, settled at most once with an operator-signed voucher. Companion to scheme_upto.md and scheme_upto_evm.md. * docs(svm/upto): address review feedback on the upto spec Squashed response to the review on #2697: - Reframe the operator as "server/facilitator" and define it up front; a server can self-facilitate — nothing in the scheme requires a separate facilitator. - Drop the `permit` profile and all EVM/Permit2 framing; `payment-channel` is the single v1 profile and the spec is single-mechanism throughout. - Remove pay-kit attribution, the hardcoded program id, and "we control" — the channel program is identified via `extra.channelProgram`. - Require `channel.authorizedSigner == operator` at verify and clarify the anti-grief / escape-hatch properties; correct channel-rent ownership (funded by and refunded to the payer; the operator sponsors only the transaction fee). - Use USDC as the `asset` example; point multi-settlement to `batch-settlement`; remove the stray multi-delegator aside. * docs(svm/upto): align with payment-channels program semantics Addresses @notorious-d-e-v's program-grounded review: 1. Role model: the operator is the channel `payee` (the program requires the `settle_and_finalize` merchant == `channel.payee`), as well as the voucher `authorizedSigner`, fee payer, and `rentPayer`. The x402 `payTo` is realized as the payee (self-facilitating) or a program-enforced distribution split (separate facilitator) — so a third-party facilitator needs no program change. 2. Verifier pins `deposit == maxAmount` (was `≥`): `topUp` can raise an open channel's deposit, so equality is required to keep the ceiling enforced. 3. Time bounds are not client-bound: `expiresAt` is the operator's voucher value (on-chain enforced); `validAfter` is off-chain verify policy. The client signs only `open`. 4. `settle_and_finalize`/`finalize` only advance status; `distribute` is what moves funds (splits, payer refund, rent return) and closes the channel. 5. Zero-amount settlement uses the no-voucher path (`has_voucher = 0`) + `distribute`, since a `cumulative = 0` voucher is non-monotonic and invalid. * docs(svm/upto): note the v1 reference is self-facilitating (operator == payTo) The separate-facilitator model (payTo as a program-enforced distribution split) is specified but not yet implemented; the reference rejects an open whose payTo is not the operator. Matches the deposit==maxAmount + recipient guard added to the implementation (PR #2694). * docs: clarify upto svm channelProgram * docs: remove upto svm decimals field * docs: trim upto svm wire format text * docs: explain upto svm channel id derivation * docs: clarify upto svm settlement transaction * docs: align upto svm asset transfer method * docs: clarify upto svm open timing * docs: document upto svm rent cleanup * docs: document upto svm facilitator splits * docs(svm): align upto spec with payment channels * doc: channel discovery * docs(svm): facilitator as zero-share payee for upto scheme Set payee = extra.feePayer (zero-share) instead of receiverAuthorizer so the rent sponsor gains a unilateral cleanup path: settle_and_seal with has_voucher = 0, then distribute and reclaim. A client/server pair can no longer strand the facilitator's rent by leaving channels open. Nonzero settlement still requires the server voucher, and the distribution always sends 100% to payTo, so the facilitator holds lifecycle authority but no payment authority. Documents the residual trust: early close refunds the unsettled remainder to the client, so servers must settle promptly. * docs(svm): define upto open acceptance policy
…utside DEFAULT_STABLECOINS (#2924) * fix and tests * fix a slight permit2 regression * Create batch-settlement-explicit-asset.md
#2693) Let the resource server embed a recent blockhash in the `exact` 402 challenge so the client can build its payment transaction without its own RPC round-trip and against a blockhash the settling RPC has already observed. - utils: `resolveBlockhash(rpc, requirements)` — prefer `extra.recentBlockhash` (+ `extra.lastValidBlockHeight`) from the challenge, fall back to `getLatestBlockhash`. The `exact` client uses it instead of an unconditional RPC call. - exact/server: `ExactSvmScheme` takes an optional `{ rpcUrl }`. When set, `enhancePaymentRequirements` fetches a fresh blockhash and emits `extra.recentBlockhash` + `extra.lastValidBlockHeight` alongside `feePayer` (best-effort — omitted on RPC failure so the client falls back). Threaded through `registerExactSvmScheme({ rpcUrl })`. - spec: document the optional `extra.recentBlockhash` / `extra.lastValidBlockHeight` fields and the client's use of them in scheme_exact_svm.md.
* add tests * patch, tests green
* fix avm caip2 * update examples
* feat: add Solana support to cloudfront-lambda-edge example Each route now offers both Base Sepolia and Solana Devnet payment options via per-route accepts arrays; schemes are registered per namespace (eip155:*/solana:*) so concrete networks come from config. Updates the guides for dual-network setup, mainnet facilitators, and the real v2 402 response shape. * chore: update examples pnpm-lock for @x402 2.19 bump * docs: keep facilitator guidance neutral, name Solana wallet examples Revert the mainnet facilitator guidance to the neutral ecosystem-list phrasing the example shipped with (no facilitator is singled out) and name Phantom/Solflare as example Solana wallets alongside MetaMask.
…2849) * specs(exact): add Starknet exact scheme for x402 v2 (spec-only) Adds the `exact` payment scheme specification for Starknet (spec-only, PR 1 of the New Chains workflow). Mechanism: the client signs a SNIP-9 Outside Execution (SNIP-12 typed data) authorizing exactly one `transfer`; the facilitator submits it via `execute_from_outside_v2` with sponsored gas — the Starknet-native analog of EIP-3009. CAIP-2 networks, exact-amount transfer, on-chain SNIP-9 nonce replay protection, canonical typed-data reconstruction, mandatory settlement simulation, and receipt-confirmed settlement effect. Sponsored-only (extra.areFeesSponsored); unsponsored is a documented follow-up. Constants verified against SNIP-9/12/6/29, the CAIP-2 registry, and Circle's docs. The reference implementation follows in a subsequent PR after spec approval. Drafted with AI assistance and human-reviewed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * specs(exact): clarify paymaster caller model and complete error codes - extra.caller: in the paymaster flow the paymaster sets the OutsideExecution Caller to its forwarder; the client verifies rather than injects (resolves the field-note vs rule-4 inconsistency) - add unexpected_verify_error / unexpected_settle_error to the error-code table - tighten wording; demote the local signature-length cap from MUST to SHOULD Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * specs(exact): align simulation wording, tighten timeout bounds, transport-agnostic flow - reconcile the index simulation bullet with rule 8: event-based criterion (exactly one asset Transfer), full call-tree simulation preferred with the documented transfer-only fallback; drop the incorrect 'plus fees' - timeout mapping: freshness band at /verify (Execute Before within skewMargin of now + maxTimeoutSeconds); minimum remaining window at settlement re-verification - strip HTTP header names from flow steps and section headings (transport-agnostic) - define absent extra.areFeesSponsored (= sponsored); name the paymaster forwarder contract as the extra.caller value; restate the settlement receipt check with rule 8's exact criterion Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * specs(exact): use core v2 error vocabulary and response field names - human-readable verify context travels in the core invalidMessage field (matches @x402/core VerifyResponse), not a scheme-invented detail field - malformed PaymentRequirements are rejected with the dedicated core code invalid_payment_requirements, not invalid_payload - reclassify unexpected_verify_error / unexpected_settle_error as standard core codes (were listed under Starknet-specific values) - document settlement_pending's intentional non-empty transaction on success:false (pending is non-terminal; the hash enables on-chain reconciliation) - drop the base64 mention from flow step 5 (transport detail, lives in the transport mapping appendix) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * specs(exact): close verification edge cases from adversarial review - apply the minimum-remaining-window floor at /verify too (was settlement-only), closing the small-maxTimeoutSeconds edge where an expired payload could pass the freshness band - require the step-4 receipt effect check before reporting a front-runner's consuming transaction as success (step 5) - areFeesSponsored:false is a requirements defect: invalid_payment_requirements (missed in the previous pass) - retention of a pending-nonce guard entry is explicitly REQUIRED; correct the idempotent-retry wording (duplicate_settlement while the guard holds) - pin ambiguous error-code mappings (accepted-mismatch, account_not_deployed vs signature-revert) - align flow step 3 and the index expiry bullet with the timeout band; anchor invalidMessage/errorMessage to the @x402/core types; tighten the settlement_pending row Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * specs(exact): tighten the Starknet index block to sibling length Match the headline style of the SVM/Stellar/TON blocks in Critical Validation Requirements: one invariant per bullet, details defer to scheme_exact_starknet.md (calldata layout, simulation topology, settlement margins live there). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * specs(exact): repair settlement retry, define Transfer, client checks Adversarial re-read of the previous two fix commits surfaced regressions and two deeper gaps; all verified against the text before fixing: - step 5 now triggers on consumed-nonce at settlement re-verification too (the idempotent-retry promise previously routed through an unreachable step 5) - step 5's rescue check is containment-scoped: a third party's consuming transaction may batch unrelated calls, and the receipt-global exactly-one criterion let a front-runner force paid-but-denied - paymaster clients MUST verify the built message against their intent before signing (Caller alone was insufficient; the signature authorizes what the message says) - define the Transfer event (selector + keyed/legacy layouts, fail closed on neither) for rule 8 and step 4 - restore index-bullet precision lost in the trim (conjunctive caller binding, settlement floor, payTo calldata) - pin remaining unmapped error codes (REVERTED, missing balance getter, failed nonce call); expired row covers the both-phases floor; smaller wording fixes (guard framing, rule-4 trusted-config predicate, RPC deployment row, eviction skew, L1 latency honesty) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * specs(exact): single-home the pending-nonce tracking requirement The pending-nonce tracking requirement had two normative homes (settlement step 4 and the Duplicate Settlement Mitigation closing paragraph). Single-home it in step 4; the mitigation section now cross-references instead of restating the MUST. Zero protection change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * specs(exact): align settlement retry, timeout, and sponsored-flag wording Three consistency fixes surfaced by the implementation pass: - step 5 also triggers on a post-eviction retry rejected with outside_execution_expired (matches the settlement re-verification path) - name the freshness lower bound explicitly and note the upper bound still applies at settlement re-verification - extra.areFeesSponsored is not matched between requirements and the accepted echo (absent is equivalent to true); each side is independently rejected if present and not true Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * specs(exact): fix step-4 retry wording and areFeesSponsored codes Two consistency fixes from the final delta review: - step 4: a post-eviction retry fails the minimum-remaining-window check (outside_execution_expired) before the nonce check; name that instead of the impossible finds-the-nonce-consumed mechanism - rule 1: give the areFeesSponsored independent-rejection codes (invalid_payment_requirements server-side, invalid_payload for the accepted echo) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * specs(exact): define a single canonical payload path for Starknet Address review feedback. - Replace the optional `extra.caller` with a REQUIRED `extra.feePayer`, matching the wire naming used by SVM and other networks. Resource servers copy it verbatim from their facilitator's `/supported` entry. - Collapse the paymaster-built vs direct construction fork into one path: the client always builds and signs the OutsideExecution itself from the PaymentRequirements alone, and never communicates with the facilitator directly. Whether the sponsor settles from its own account or routes through a forwarder/paymaster is facilitator-local and never touches the wire. - Drop `extra.areFeesSponsored`; a required `feePayer` already implies it. - Forbid the SNIP-9 ANY_CALLER sentinel as a `feePayer` value, so a caller-bound authorization cannot silently become a bearer one. - Remove the HTTP header table; the scheme stays transport agnostic. - Remove the USDC address table and describe `asset` generically via SNIP-2 rather than ERC-20. - State response-field requirements behaviourally instead of referring to `@x402/core` types. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…xample (#2876) Adds service_name / tags to both RouteConfigs (parity with the TypeScript advanced bazaar example) and documents the resource-block service metadata and its indexer caps in the README. Without these fields a discovered service is catalogued under its raw domain with no name, tags, or icon.
…ry) (#2941) * docs: add NEAR x402 Facilitator to the facilitators table * site: add NEAR x402 Facilitator ecosystem partner entry * listing: drop ecosystem-page entry (page deprecated per maintainer)
The repo moved from coinbase/x402 to x402-foundation/x402; the console guide's clone command still pointed at the old location.
* add facilitator faq * minor fixes
) HTTPFacilitatorClient's `createAuthHeaders` callback must return an object keyed by facilitator path (`verify`/`settle`/`supported`). Returning a flat headers object silently indexed to `undefined` and dropped auth on every request, surfacing as an unexplained 401. Throw a clear error on the wrong shape and document the expected shape. Fixes #2762
…#2937) * align ts/go * add py * add changeset
…it rejection (#2974) * fix: add request timeouts to HTTPFacilitatorClient and guard eager init rejection verify(), settle(), and getSupported() previously called fetch() with no deadline, so a facilitator that accepted a connection but never completed the response hung the operation indefinitely — and, through the eagerly created initPromise shared by the Hono/Express/Fastify/Next middlewares, wedged every protected route until restart. - Add FacilitatorConfig.timeoutMs (default 30s, matching the Go and Python facilitator clients), applied via a fresh AbortSignal.timeout() per HTTP attempt, covering response headers and body consumption. - Reject with a typed FacilitatorTimeoutError (a FacilitatorResponseError subclass the middlewares already surface as 502) instead of a raw DOMException; settle() timeouts are documented as indeterminate. - Attach a rejection handler to the eager initPromise in all four middlewares so an early init failure cannot become an unhandled rejection; the first protected request still observes it and retries. Closes #2961 * fix: surface deadline aborts from error-body reads and validate timer-safe timeoutMs Review follow-ups on #2974: - getSupported() swallowed a deadline abort raised while reading a non-2xx error body, reporting it as a generic HTTP failure — which middleware surfaces as a 500 instead of the typed 502, and which the 429 path would even retry after the deadline had fired. Abort/timeout rejections from response.text() are now rethrown so the FacilitatorTimeoutError conversion applies; statusText remains the fallback for other body-read failures. - timeoutMs now requires a positive safe integer of at most 2^31 - 1: AbortSignal.timeout() throws ERR_OUT_OF_RANGE on non-integers at request time, and larger values overflow Node's 32-bit timers into an effective ~1ms deadline while reporting the configured duration.
* fix enrichPaymentPayload * same for go * same for py
* fix(go/http): add Cache-Control: no-store to 402 responses * add cache-control policy for payment HTTP responses --------- Co-authored-by: Philippe d'Argent <pdargent@icloud.com>
* fix(ts/py): add cache control, no-store for 402, private for 200 * add changeset
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Tests
Checklist