feat: model the realtime-funding refund destination as an external account - #783
feat: model the realtime-funding refund destination as an external account#783ls-bolt[bot] wants to merge 2 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
…count Adds an optional `refundAccountId` to `RealtimeFundingQuoteSource`, referencing an existing external account rather than a free-text address, so the refund target goes through whitelisting (`status`), the trust/untrust confirm flow, and beneficiary verification instead of bypassing them. Documents the fallback chain: omitted falls back to the customer's internal account for that asset, and a customer with no internal account to fall back on gets a new `REFUND_DESTINATION_REQUIRED` 400 rather than a deposit that cannot be returned. Bitcoin L1 was the only crypto corridor with no `ExternalAccountType` member, so a BTC L1 refund target was inexpressible. Adds `BITCOIN_L1` plus `BitcoinWalletExternalAccountInfo` and its shared `BitcoinWalletInfo` address shape, wired into both external-account oneOfs. Co-Authored-By: jklein24 <jklein24@users.noreply.github.com> Co-Authored-By: peter.rojs <peter.rojs@lightspark.com>
|
✱ Stainless preview builds for gridThis PR will update the cli go kotlin openapi php python ruby typescript Edit this comment to update them. They will appear in their respective SDK's changelogs. ✅ grid-typescript studio · code · diff
✅ grid-openapi studio · code · diff
✅ grid-ruby studio · code · diff
✅ grid-go studio · code · diff
✅ grid-kotlin studio · code · diff
|
| 💡 Schema/IsAmbiguous: Missing type for schema |
✅ grid-php studio · code · diff
Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ✅→lint ✅→test ✅New diagnostics (1 note)
💡 Schema/IsAmbiguous: Missing type for schema
✅ grid-cli studio · code · diff
Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ⚠️→build ❗→lint ❗→test ❗New diagnostics (1 note)
💡 Schema/IsAmbiguous: Missing type for schema
This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push.
If you push custom code to the preview branch, re-run this workflow to update the comment.
Last updated: 2026-07-31 20:56:46 UTC
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|

Summary
The Bitcoin L1 deposit-address work added a free-text
refundAddressto the realtime-funding quote source, which was pulled before merge and deferred. This lands it properly: the refund target is now a reference to an existing external account rather than a raw address, so it goes through whitelisting (status), the trust/untrust confirm flow, and beneficiary verification instead of bypassing all three.Three parts:
1.
refundAccountIdonRealtimeFundingQuoteSource— optional. A bare external-account ID string, matching theaccountIdidiom already used byAccountQuoteSourceandAccountDestination. Must belong tocustomerId, beACTIVE, and match the funding source on both currency and network — a USDC deposit can't refund to a USDT account on the same chain.2. A documented fallback chain. Omitted → funds return to the customer's internal account for that asset. No internal account to fall back on → quote creation is rejected with a new
REFUND_DESTINATION_REQUIRED400 rather than accepting a deposit that can't be returned. That rejection was previously undocumented behavior; it's now real API surface, listed in both theError400code table and its enum.3.
BITCOIN_L1external-account type. Every other crypto corridor (BASE_WALLET,ETHEREUM_WALLET,PLASMA_WALLET,POLYGON_WALLET,SOLANA_WALLET,SPARK_WALLET,TRON_WALLET) already has a member; BTC L1 did not, so a BTC L1 refund target was inexpressible. Adds the type plusBitcoinWalletExternalAccountInfoand its sharedBitcoinWalletInfoaddress shape, wired into both the read and create external-accountoneOfs.The destination-side
refundAddressis deliberately not included. A failed crypto payout refunds to an address Grid already knows, andAccountDestinationalso covers fiat accounts where a refund address is meaningless.Changes
openapi/components/schemas/quotes/RealtimeFundingQuoteSource.yamlrefundAccountId+ fallback-chain docsopenapi/components/schemas/common/BitcoinWalletInfo.yamlopenapi/components/schemas/external_accounts/BitcoinWalletExternalAccountInfo.yamloneOfmemberopenapi/components/schemas/external_accounts/ExternalAccountType.yamlBITCOIN_L1.../ExternalAccountInfoOneOf.yaml,.../ExternalAccountCreateInfoOneOf.yamlopenapi/components/schemas/errors/Error400.yamlREFUND_DESTINATION_REQUIREDin the code table and the enumopenapi/paths/quotes/quotes.yamlcryptoFundingWithRefundAccountrequest example;400description notes the new code.stainless/stainless.ymlBaseExternalAccountInfoallOf[0]strip target for the new memberopenapi.yaml,mintlify/openapi.yamlmake buildNo
info.versionbump — every change is additive, so no newservers.urlpath.Test plan
Spec-only repo, so lint plus structural verification of the generated bundle:
make lint-openapi— 0 errors. The twoschema-properties-have-descriptions/-exampleswarnings onBitcoinWalletInfo.accountTypeare identical to the ones every sibling wallet schema already carries (EthereumWalletInfo,SparkWalletInfo), i.e. consistent with the established pattern.make buildrun twice — bundles are byte-identical on re-run, so no generation drift.BitcoinWalletExternalAccountInfois listed in bothoneOfs with aBITCOIN_L1mapping that resolves to a listed member; no discriminator mapping target in eitheroneOfis dangling;Error400's markdown table andenumhave zero symmetric difference (no drift in either direction);refundAccountIdis present and not required;refundAddressappears nowhere in either bundle.BASE_WALLEToccurrences are single illustrative payloads andsnippets/error-handling.mdxdocuments four hand-picked codes narratively rather than mirroring the enum, so no MDX change is needed.Notes for the reviewer
refundAccountIdandREFUND_DESTINATION_REQUIREDare described here before they're honored end-to-end, the same wayBITCOIN_L1shipped ahead of the server previously. Flagged and approved before implementation, but worth a second look if you'd rather it land alongside the backend change.breaking-changelabel, as expected. oasdiff reports 9 errors / 530 warnings. All 9 errors are the sameresponse-property-one-of-addedforBitcoinWalletExternalAccountInfoacross the three external-account read/create endpoint families; the 530 warnings areresponse-property-enum-value-addedforBITCOIN_L1andREFUND_DESTINATION_REQUIRED. Additive with no removals — adding toExternalAccountTypepropagates toaccountTypeon every member inheritingBaseExternalAccountInfo, so the list is wide but shallow.Schema/IsAmbiguous: Missing type for schema, reported once per SDK. It's the composedallOf-only wrapper having notypeof its own; all seven existing wallet members have exactly the same shape, so this matches the established pattern rather than deviating from it. Addingtype: objectto just the new one would make it the odd member out; worth a separate sweep across all eight if the SDK team wants it silenced.❗lint/test stages in the Stainless preview are pre-existing.grid-go,grid-python, andgrid-clishow the identical failure pattern on already-merged PRs (e.g. Add USD account bank, account type and wire routing fields #778), and thepreviewcheck still concludes green here. Not a regression from this change.mintlify/docs.jsonpins the API reference to Stainless's hosted published spec, so the rendered reference only picks this up after merge and republish.