Skip to content

feat: add onChainTransaction to transaction source/destination#680

Closed
ls-bolt[bot] wants to merge 1 commit into
mainfrom
07-10-grid-onchain-tx-source-dest
Closed

feat: add onChainTransaction to transaction source/destination#680
ls-bolt[bot] wants to merge 1 commit into
mainfrom
07-10-grid-onchain-tx-source-dest

Conversation

@ls-bolt

@ls-bolt ls-bolt Bot commented Jul 10, 2026

Copy link
Copy Markdown

This PR has been claimed. The active PR is now #681.

Summary

Adds an optional onChainTransaction (transactionHash + network) to BaseTransactionSource and BaseTransactionDestination, so every source/destination variant surfaces the on-chain transfer for a leg whose counterparty is an external crypto wallet.

  • network is environment-qualified (SOLANA_MAINNET vs SOLANA_DEVNET, etc.) so the hash can be looked up on the correct explorer.
  • Co-located with the leg it describes — the same place RealtimeFundingTransactionSource already carries traceNumber/endToEndId (the bank-rail analog). A bridge flow (crypto in on one chain → crypto out on another) populates both legs, each with its own hash/network.
  • Sharpens ReconciliationInstructions docs to distinguish its settlement-layer transactionHash (for UMA sends, the inter-VASP leg) from the new per-leg field. No deprecation.

Additive change — no info.version bump.

Context

Grid should return on-chain transaction info for any transaction whose source or destination is an external crypto wallet, covering Fireblocks-settled and sandbox flows in both directions. This is the public-spec half; the sparkcore backend wiring + vendored SDK regen land in a separate webdev PR.

Slack thread: https://lightsparkgroup.slack.com/archives/D0AHLSKKV8R/p1783721701181659

Reply with a comment (e.g. LGTM) to approve — emoji reactions don't notify me here.


🤖 ionized-nexus(#1) | Feedback

@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
grid-flow-builder Ignored Ignored Preview Jul 11, 2026 12:28am
grid-wallet-demo Ignored Ignored Preview Jul 11, 2026 12:28am

Request Review

@ls-bolt ls-bolt Bot added the bolt label Jul 10, 2026

akanter commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

✱ Stainless preview builds for grid

This PR will update the grid SDKs with the following commit messages.

cli

chore(internal): regenerate SDK with no functional changes

go

docs(types): update ReconciliationInstructions documentation

kotlin

feat(api): add onChainTransaction field to transaction source and destination models

openapi

feat(api): add OnChainTransaction model and fields to transaction source/destination

php

feat(api): add onChainTransaction field to BaseTransactionSource and BaseTransactionDestination

python

docs(types): update ReconciliationInstructions model documentation

ruby

feat(api): add on_chain_transaction to transaction source/destination models

typescript

feat(api): add onChainTransaction to BaseTransactionSource and BaseTransactionDestination

Edit this comment to update them. They will appear in their respective SDK's changelogs.

grid-openapi studio · code · diff

Your SDK build had at least one "warning" diagnostic, but this did not represent a regression.
generate ⚠️

grid-ruby studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅ (prev: build ⏭️) → lint ✅test ✅

grid-go studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅ (prev: build ⏭️) → lint ❗test ❗

go get github.com/stainless-sdks/grid-go@a3db3f9060581410ab495896263fb486ff27d0b5
grid-kotlin studio · code · diff

Your SDK build had at least one "warning" diagnostic, but this did not represent a regression.
generate ⚠️build ✅ (prev: build ⏭️) → lint ✅ (prev: lint ⏭️) → test ❗

⚠️ grid-typescript studio · code · diff

Your SDK build had a failure in the lint CI job, which is a regression from the base state.
generate ✅build ✅ (prev: build ⏭️) → lint ❗ (prev: lint ⏭️) → test ✅

npm install https://pkg.stainless.com/s/grid-typescript/4278263992c1de30ea38d7ebc8c642745c1e85b3/dist.tar.gz
⚠️ grid-python studio · code · diff

Your SDK build had a failure in the lint CI job, which is a regression from the base state.
generate ✅build ✅ (prev: build ⏭️) → lint ❗ (prev: lint ⏭️) → test ❗

pip install https://pkg.stainless.com/s/grid-python/46c75a7e0a6d15be30c90597c7ba50f332667e02/grid-0.0.1-py3-none-any.whl
grid-php studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅lint ✅test ✅

grid-cli studio · code · diff

Your SDK build had at least one "warning" diagnostic, but this did not represent a regression.
generate ⚠️build ❗lint ❗test ❗


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-11 00:32:53 UTC

description: On-chain transaction hash of the crypto transfer for this leg of the transaction.
example: '4Nd1m6Qkq7RfKuE5vQ9qP9Tn6H94Ueqb4xXHzsAbd8WgpD9k6oRnJm2pQ7sT1uV3wX5yZ6aB8cD9eF0gH1i'
network:
type: string

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we already have an enum like this anywhere in the API?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question — I checked, and no, there's no existing enum for this. The only network-ish thing in the spec is cryptoNetwork on EstimateCryptoWithdrawalFeeRequest, and it's a free-form type: string with bare, non-environment-qualified example values (SOLANA, ETHEREUM, …) — no enum, no mainnet/devnet distinction.

So I've extracted this into a reusable named schema CryptoNetwork (openapi/components/schemas/crypto/CryptoNetwork.yaml) and onChainTransaction.network now $refs it, so it's not a one-off and future fields can share it. I kept it environment-qualified (SOLANA_MAINNET / SOLANA_DEVNET) because for an on-chain tx you need to know the environment to hit the right explorer — that's the one thing the existing bare string can't express.

I left the existing cryptoNetwork input string alone for now (converging it to this enum would change accepted input values = a breaking change on that endpoint), but it's the obvious candidate to adopt this enum later for consistency. Happy to do that convergence in a follow-up if you want it.

Transaction hash of the settlement transfer that delivered funds to the
transaction's destination, when available. For UMA payments this is the inter-VASP
settlement leg (e.g. USDC on Solana to the receiving partner), not a transfer to a
customer's own wallet. When the destination is itself an external crypto wallet this

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we actually remove the external wallet destination from this spot? It feels weird to explicitly specify that in two places.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — specifying it in two places is confusing. Fixed: reconciliationInstructions.transactionHash is now scoped purely to the inter-VASP settlement leg of a UMA payment (the internal settlement detail), and no longer mentions the external-wallet destination. When the destination is an external crypto wallet, the hash lives only on destination.onChainTransaction — one home, no overlap.

I've also updated the sparkcore plan so the backend matches the docs: _gen_reconciliation_instructions will not populate transactionHash when the destination is an external crypto wallet (that hash goes to destination.onChainTransaction instead) — it stays populated only for the settlement-layer/UMA case. Note that's a small behavior change to the existing field for direct crypto withdrawals (hash moves from here to onChainTransaction); calling it out explicitly since it's technically observable.

Adds an optional onChainTransaction (transactionHash + network) to
BaseTransactionSource and BaseTransactionDestination for legs whose counterparty is
an external crypto wallet. network references a new reusable CryptoNetwork enum
(environment-qualified: mainnet vs devnet/testnet/regtest). Reconciliation
instructions' transactionHash is now scoped purely to the inter-VASP settlement leg,
with the external-wallet endpoint hash living only on the source/destination.
Additive, no version bump.
@ls-bolt
ls-bolt Bot force-pushed the 07-10-grid-onchain-tx-source-dest branch from eab4de5 to 2da1605 Compare July 11, 2026 00:28
@ls-bolt

ls-bolt Bot commented Jul 11, 2026

Copy link
Copy Markdown
Author

Revision 2 (addressing review)

  • @jklein24 (enum reuse): No existing enum for this — the only network-ish thing was a free-form cryptoNetwork string on EstimateCryptoWithdrawalFeeRequest (bare names, no environment). Extracted the network values into a reusable named schema CryptoNetwork (components/schemas/crypto/CryptoNetwork.yaml, environment-qualified) and onChainTransaction.network now $refs it. Left the existing loose string alone (converging it would be a breaking input change) — flagged as a possible follow-up.
  • @jklein24 (double-specification): Scoped reconciliationInstructions.transactionHash purely to the inter-VASP settlement leg; removed the external-wallet-destination cross-reference so the endpoint hash lives in exactly one place (destination.onChainTransaction). The sparkcore plan is updated so the backend matches (won't populate reconciliationInstructions.transactionHash for external-wallet destinations).

make build + make lint-openapi clean (0 errors). No version bump.


🤖 ionized-nexus(#1) | Feedback

@jklein24 jklein24 closed this Jul 11, 2026
jklein24 added a commit that referenced this pull request Jul 13, 2026
## Summary

Adds an optional `onChainTransaction` (`transactionHash` + `network`) to
`BaseTransactionSource` and `BaseTransactionDestination`, so every
source/destination variant surfaces the on-chain transfer for a leg
whose counterparty is an external crypto wallet.

- `network` is environment-qualified (`SOLANA_MAINNET` vs
`SOLANA_DEVNET`, etc.) so the hash can be looked up on the correct
explorer.
- Co-located with the leg it describes — the same place
`RealtimeFundingTransactionSource` already carries
`traceNumber`/`endToEndId` (the bank-rail analog). A bridge flow (crypto
in on one chain → crypto out on another) populates both legs, each with
its own hash/network.
- Sharpens `ReconciliationInstructions` docs to distinguish its
**settlement-layer** `transactionHash` (for UMA sends, the inter-VASP
leg) from the new per-leg field. No deprecation.

Additive change — no `info.version` bump.

## Context

Grid should return on-chain transaction info for any transaction whose
source or destination is an external crypto wallet, covering
Fireblocks-settled and sandbox flows in both directions. This is the
public-spec half; the sparkcore backend wiring + vendored SDK regen land
in a separate webdev PR.

Slack thread:
https://lightsparkgroup.slack.com/archives/D0AHLSKKV8R/p1783721701181659

Reply with a comment (e.g. LGTM) to approve — emoji reactions don't
notify me here.

---
🤖
[ionized-nexus](https://zeus.dev.dev.sparkinfra.net/#/arc?id=ionized-nexus)[(#1)](https://zeus.dev.dev.sparkinfra.net/#/instance?id=ionized-nexus)
| [Feedback](https://zeus.dev.dev.sparkinfra.net/feedback)

Original PR: #680

---------

Co-authored-by: Jeremy <jeremy@lightspark.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants