Skip to content

feat: TON wallet adapter#1038

Open
ted-palmer wants to merge 11 commits into
mainfrom
ted/int2-639-add-ton-wallet-adapter-to-relay-kit
Open

feat: TON wallet adapter#1038
ted-palmer wants to merge 11 commits into
mainfrom
ted/int2-639-add-ton-wallet-adapter-to-relay-kit

Conversation

@ted-palmer

Copy link
Copy Markdown
Collaborator

No description provided.

@ted-palmer ted-palmer requested a review from pedromcunha June 22, 2026 13:38
@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
relay-sdk-demo Ready Ready Preview, Comment Jun 25, 2026 1:55pm

Request Review

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ted-palmer's task in 1m 33s —— View job


📝 Docs Drift Check — Confidence: HIGH

What changed: A new public wallet adapter package @relayprotocol/relay-ton-wallet-adapter was added, exposing adaptTonWallet(walletAddress, sendTransaction, options?). It registers tonvm as a supported VM type and lets the Relay SDK execute deposits/bridges against a connected TON wallet via a caller-supplied sign-and-broadcast callback.

Docs impact: The Adapters reference page is now stale — it does not list tonvm as a supported VM type, omits TON from the list of officially maintained adapters, and has no TON usage example. No new page is needed; the existing page is the structural home.

Affected pages (paths inside relayprotocol/relay-docs):

  • references/relay-kit/sdk/adapters.mdx — update

Draft:

> Replace row in the interface table: the `vmType` row

| **vmType**                    | A string representing a supported vmType (`evm`  `svm`  `bvm`  `tvm` `lvm` `tonvm`)                                                   ||
> Insert after: the `[Lighter Adapter]` entry under `### What adapters are available out of the box?`

[TON Adapter](https://github.com/relayprotocol/relay-kit/tree/main/packages/relay-ton-wallet-adapter): This adapter gives the SDK the ability to submit transactions on the TON blockchain. The user's key stays in their wallet, so the adapter never signs — you pass a `sendTransaction` callback (for example wrapping Dynamic's TON connector or TonConnect UI) that signs and broadcasts the request, while the adapter handles request building and on-chain confirmation. Confirmation reads default to a public toncenter endpoint; pass your own `@ton/ton` `TonClient` or an `endpoint` via the optional `options` argument for production use. TON support requires the `@ton/core` and `@ton/ton` peer dependencies in addition to `viem` and `@relayprotocol/relay-sdk`.
> Insert after: the `Lighter` tab inside the `<CodeGroup>` under `### How can I use an adapter?` (before the closing `</CodeGroup>`)

```typescript TON
import { getClient, Execute, getQuote } from "@relayprotocol/relay-sdk"
import { adaptTonWallet } from '@relayprotocol/relay-ton-wallet-adapter'

// The user's key lives in their TON wallet, so the adapter never signs. You
// provide a sendTransaction callback that forwards the TonConnect-style request
// to your wallet provider (e.g. Dynamic's TON connector or tonConnectUI), signs
// + broadcasts it, and returns the result. The adapter accepts a signed
// external-message { boc } (what most TonConnect wallets return) or a
// { transactionHash }.
const adaptedWallet = adaptTonWallet(walletAddress, async (request) => {
  const { boc } = await wallet.sendTransaction(request)
  return { boc }
})

const options = ... // define this based on getQuote options

const quote = await getClient().actions.getQuote(options)

getClient().actions.execute({
  quote,
  wallet: adaptedWallet,
  onProgress: ({ steps, fees, breakdown, currentStep, currentStepItem, txHashes, details }) => {
    // custom handling
  },
  ...
})
```

Needs human input:

  • TON message signing (handleSignMessageStep) is intentionally not implemented (not used by deposit/bridge flows). The interface table currently marks handleSignMessageStep as required ✅; no change is proposed here, but a reviewer may want a short note that TON throws on this step.

To publish as a draft PR in relayprotocol/relay-docs, reply on this PR with:

/publish-docs-pr

A separate workflow will open a draft PR attributed to you. Edit the draft freely before marking it ready for review.

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ted-palmer's task in 2m 41s —— View job


Code Review

  • Gather context (diff, commits)
  • Review TON wallet adapter
  • Review SDK changes
  • Review UI hooks (useTonBalance, useCurrencyBalance)
  • Review demo changes

The core TON adapter is well-built and clearly documented. The tonvm plumbing is consistent across the SDK types, balance hooks, token selectors, and demo wiring. The confirmation logic (external-message hash matching + lenient origin-success check) and the bounce-flag re-encoding are correct and thoughtfully commented. No functional/correctness bugs found in the adapter, useTonBalance, or useCurrencyBalance.

The findings below are all about unrelated changes bundled into this PR (a repo guideline), not the TON feature itself.


Code Review — 3 issue(s) found

  1. [NOTE] Unrelated changes: full OpenAPI regeneration
    packages/sdk/src/types/api.ts (+511/-616), packages/sdk/src/routes/index.ts — This appears to be a wholesale regeneration of the API spec that is unrelated to TON: it adds x-api-key headers across endpoints, adds /balance-events/{wallet}, removes /execute/swap/multi-input from the routes array, and reorders the gasCurrency/fee-currency enums (ton was already present pre-PR). The TransactionStepItem.messages field that TON actually needs was added by hand, not generated here. None of this is wrong, but bundling a ~1100-line spec regen into a feature PR makes review harder and risks shipping unintended API surface changes. Consider splitting it into its own commit/PR. (I confirmed nothing in the repo references multi-input, so its removal is harmless.)

  2. [NOTE] Unrelated formatting churn that conflicts with conventions
    packages/sdk/src/constants/address.ts (+25/-25) — The entire file was reformatted to double quotes + semicolons, which conflicts with the repo's Prettier config / AGENTS.md rule 7 (no semicolons, single quotes). There is no functional TON change here — tonDeadAddress already existed before this PR — so this is pure churn that reverses the established style. Recommend reverting to single-quote/no-semicolon formatting.

  3. [NOTE] Large reformatting churn for a one-line change
    demo/components/CustomizeSidebar.tsx (+413/-418) — The only meaningful change is adding 'tonvm' to WALLET_VM_TYPES; the remaining ~830 lines are Prettier reformatting of a previously-unformatted file. This buries the real change. Consider keeping just the 'tonvm' addition (or landing the reformat separately).


Nice work on the adapter itself — the documentation around bounceable address encoding and the message-hash reconciliation is especially clear.

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ted-palmer's task in 1m 45s —— View job


Code Review

  • Gather context (diff, commits)
  • Review TON wallet adapter (adapter.ts, types.ts)
  • Review SDK changes (types, transaction utils)
  • Review UI hooks (useTonBalance, useCurrencyBalance)
  • Review demo wiring

The TON adapter is well-built and the tonvm plumbing is consistent across the SDK union types (AdaptedWallet, Execute, TransactionConfirmationError, transaction.ts), the balance hooks, isValidAddress, the token selectors, and the demo. The confirmation logic (external-message hash reconciliation + the deliberately-lenient origin-success check) and the bounce-flag re-encoding are correct and clearly commented. No functional/correctness bugs found in the adapter, useTonBalance, or useCurrencyBalance.

Note: the constants/address.ts double-quote/semicolon churn flagged in the earlier review is now resolved (no diff against origin/main). The remaining findings are all about unrelated changes bundled into this PR (a repo guideline), not the TON feature itself.


Code Review — 2 issue(s) found

  1. [NOTE] Unrelated bundled change: full OpenAPI regeneration
    packages/sdk/src/types/api.ts (+511/-616), packages/sdk/src/routes/index.ts — This is a wholesale regen of the API spec unrelated to TON: it adds x-api-key headers across endpoints, adds /balance-events/{wallet}, and removes /execute/swap/multi-input from the routes array. The one field TON actually needs (TransactionStepItem.data.messages) was added by hand in TransactionStepItem.ts, not generated here. Nothing is wrong, but bundling a ~1100-line spec regen into a feature PR makes review harder and risks shipping unintended API-surface changes. Consider splitting it into its own commit/PR. (Confirmed nothing references multi-input, so its removal is harmless.)

  2. [NOTE] Unrelated reformatting churn around a one-line change
    demo/components/CustomizeSidebar.tsx (+413/-418) — The only meaningful change is adding 'tonvm' to WALLET_VM_TYPES; the remaining ~830 lines are Prettier reformatting of a previously-unformatted file, which buries the real change. Consider keeping just the 'tonvm' addition (or landing the reformat separately).


Nice work — the documentation around bounceable-address encoding and the message-hash reconciliation between the signed BOC and the on-chain inbound message is especially clear.

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ted-palmer's task in 1m 19s —— View job


📝 Docs Drift Check — Confidence: HIGH

What changed: A new public wallet adapter package @relayprotocol/relay-ton-wallet-adapter was added, exposing adaptTonWallet(walletAddress, sendTransaction, options?). It registers tonvm as a supported VM type and lets the Relay SDK execute deposits/bridges against a connected TON wallet via a caller-supplied sign-and-broadcast callback.

Docs impact: The Adapters reference page is stale — it does not list tonvm as a supported VM type, omits TON from the officially maintained adapters list, and has no TON usage example. No new page is needed; the existing page is the structural home.

Affected pages (paths inside relayprotocol/relay-docs):

  • references/relay-kit/sdk/adapters.mdx — update

Draft:

> Replace: the `vmType` row in the interface table under `### What is an adapter anyway?`

| **vmType**                    | A string representing a supported vmType (`evm`  `svm`  `bvm`  `tvm` `lvm` `tonvm`)                                                   ||
> Insert after: the `[Lighter Adapter]` entry under `### What adapters are available out of the box?`

[TON Adapter](https://github.com/relayprotocol/relay-kit/tree/main/packages/relay-ton-wallet-adapter): This adapter gives the SDK the ability to submit transactions on the TON blockchain. The user's key stays in their wallet, so the adapter never signs — you pass a `sendTransaction` callback (for example wrapping Dynamic's TON connector or TonConnect UI) that signs and broadcasts the request, while the adapter handles request building and on-chain confirmation. Confirmation reads default to a public toncenter endpoint; pass your own `@ton/ton` `TonClient` or an `endpoint` via the optional `options` argument for production use. TON support requires the `@ton/core` and `@ton/ton` peer dependencies in addition to `viem` and `@relayprotocol/relay-sdk`.
> Insert after: the `Lighter` tab inside the `<CodeGroup>` under `### How can I use an adapter?` (before the closing `</CodeGroup>`)

```typescript TON
import { getClient, Execute, getQuote } from "@relayprotocol/relay-sdk"
import { adaptTonWallet } from '@relayprotocol/relay-ton-wallet-adapter'

// The user's key lives in their TON wallet, so the adapter never signs. You
// provide a sendTransaction callback that forwards the TonConnect-style request
// to your wallet provider (e.g. Dynamic's TON connector or tonConnectUI), signs
// + broadcasts it, and returns the result. The adapter accepts a signed
// external-message { boc } (what most TonConnect wallets return) or a
// { transactionHash }.
const adaptedWallet = adaptTonWallet(walletAddress, async (request) => {
  const { boc } = await wallet.sendTransaction(request)
  return { boc }
})

const options = ... // define this based on getQuote options

const quote = await getClient().actions.getQuote(options)

getClient().actions.execute({
  quote,
  wallet: adaptedWallet,
  onProgress: ({ steps, fees, breakdown, currentStep, currentStepItem, txHashes, details }) => {
    // custom handling
  },
  ...
})
```

Needs human input:

  • TON message signing (handleSignMessageStep) is intentionally not implemented (not used by deposit/bridge flows) and throws if invoked. The interface table marks handleSignMessageStep as required ✅; no change is proposed here, but a reviewer may want to add a short note that the TON adapter does not implement this step.

To publish as a draft PR in relayprotocol/relay-docs, reply on this PR with:

/publish-docs-pr

A separate workflow will open a draft PR attributed to you. Edit the draft freely before marking it ready for review.

@ted-palmer

Copy link
Copy Markdown
Collaborator Author

/publish-docs-pr

@github-actions

Copy link
Copy Markdown
Contributor

🚚 Docs Draft PR — starting publish to relayprotocol/relay-docs, requested by @ted-palmer. I'll post the PR link here when it's ready.

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ted-palmer's task in 1m 2s —— View job


Docs update materialized ✅

Applied the drafted TON adapter docs to the cloned relay-docs repo. A separate workflow will open the draft PR.

  • Load draft from drift-check comment
  • Read docs style guide (AGENTS.md)
  • Read target page references/relay-kit/sdk/adapters.mdx
  • Apply edits (vmType row, TON adapter entry, TON code tab)
  • Verify style-guide conformance
  • Emit publish summary

Changes — all in references/relay-kit/sdk/adapters.mdx (update):

  1. Added tonvm to the supported vmType list in the interface table.
  2. Added the TON Adapter entry to the officially-maintained adapters list (after Lighter).
  3. Added a TON tab to the <CodeGroup> usage example (after Lighter, before </CodeGroup>).

Conformance: SDK reference profile (§3.4) — frontmatter intact, no new headings, external GitHub links match sibling adapter entries, code tab under 45 lines so no expandable needed.

Note for reviewer: The interface table marks handleSignMessageStep as required ✅, but the TON adapter intentionally does not implement it (unused by deposit/bridge flows; throws if invoked). No change was proposed for that row — you may want to add a short caveat.

DOCS_PUBLISH_SUMMARY_START
files_changed:
  - path: references/relay-kit/sdk/adapters.mdx
    action: update
notes:
  - All three draft blocks were action=update against an existing file; applied as surgical edits.
  - handleSignMessageStep stays marked required in the interface table; TON does not implement it. Flagged for human reviewer (no edit made).
DOCS_PUBLISH_SUMMARY_END

@github-actions

Copy link
Copy Markdown
Contributor

Docs Draft PR opened: relayprotocol/relay-docs#343

@ted-palmer is assigned on the draft PR. Review and mark ready when it's good.

const getReadClient = (): TonClient => {
if (!_client) {
_client = new TonClient({
endpoint: options?.endpoint ?? DEFAULT_TON_RPC

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

if the user changes endpoints to we recreate?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Currently no

Comment thread packages/relay-ton-wallet-adapter/src/adapter.ts Outdated
Comment thread packages/relay-ton-wallet-adapter/tsconfig.base.json
Comment thread packages/relay-ton-wallet-adapter/tsconfig.build.json
Comment thread packages/relay-ton-wallet-adapter/tsconfig.json
// JSON-RPC gateway (drpc) that doesn't reliably serve `getAddressBalance`
// without a key, so we hit toncenter's REST endpoint directly — mirroring how
// the Tron balance hook hardcodes trongrid rather than using the chain RPC.
const TON_API_BASE = 'https://toncenter.com/api/v2'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe we should have a way to override this via chain configs.

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ted-palmer's task in 1m 38s —— View job


Code Review

  • Gather context (diff, commits)
  • Review TON wallet adapter (adapter.ts, types.ts)
  • Review SDK changes (types, transaction utils, routes)
  • Review UI hooks (useTonBalance, useCurrencyBalance)
  • Review demo wiring

The TON adapter is well-built and the tonvm plumbing is consistent across the SDK union types (AdaptedWallet, Execute, TransactionConfirmationError, transaction.ts), the balance hooks, isValidAddress (via isTonAddress), the token selectors, and the demo. The external-message hash reconciliation between the signed BOC and the on-chain inbound message, the deliberately-lenient origin-success check, and the bounce-flag re-encoding are all correct and clearly commented. No functional/correctness bugs found in the adapter, useTonBalance, or useCurrencyBalance.

I also confirmed the two open review threads are handled in the latest code:

  • Endless while loop (pedromcunha) — handleConfirmTransactionStep now uses a bounded for loop with a maxAttempts sentinel (adapter.ts:129-131) in addition to the wall-clock timeout. ✅
  • constants/address.ts quote/semicolon churn flagged in earlier rounds — no longer in the diff. ✅

The remaining findings are all about unrelated changes bundled into this PR (a repo guideline: "No unrelated changes bundled into the PR"), not the TON feature itself.


Code Review — 2 issue(s) found

  1. [NOTE] Architecture: full OpenAPI regeneration bundled in
    packages/sdk/src/types/api.ts (+511/-616), packages/sdk/src/routes/index.ts — This is a wholesale regen of the API spec that's unrelated to TON: it adds x-api-key headers across endpoints, adds /balance-events/{wallet}, and removes /execute/swap/multi-input from the routes array. The one field TON actually needs (TransactionStepItem.data.messages) was added by hand in TransactionStepItem.ts, not generated here. Nothing is functionally wrong (I confirmed nothing in the repo references multi-input, so its removal is harmless), but bundling a ~1100-line spec regen into a feature PR makes review harder and risks shipping unintended API-surface changes. Consider splitting it into its own commit/PR.

  2. [NOTE] Architecture: reformatting churn buries a one-line change
    demo/components/CustomizeSidebar.tsx (+413/-418) — The only meaningful change is adding 'tonvm' to WALLET_VM_TYPES; the remaining ~830 lines are Prettier reformatting of a previously-unformatted file, which buries the real change and inflates the diff. Consider keeping just the 'tonvm' addition (or landing the reformat as a separate commit).


Nice work on the adapter — the BOC/inbound-message hash reconciliation and the bounceable-address handling are especially clear, and the sendTransaction-callback design (adapter never holds the key) is a clean fit with the other VM adapters.

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ted-palmer's task in 1m 40s —— View job


📝 Docs Drift Check — Confidence: HIGH

What changed: A new public wallet adapter package @relayprotocol/relay-ton-wallet-adapter was added, exposing adaptTonWallet(walletAddress, sendTransaction, options?). It registers tonvm as a supported VM type and lets the Relay SDK execute deposits/bridges against a connected TON wallet via a caller-supplied sign-and-broadcast callback.

Docs impact: The Adapters reference page is stale — it does not list tonvm as a supported VM type, omits TON from the officially maintained adapters list, and has no TON usage example. No new page is needed; the existing page is the structural home.

Affected pages (paths inside relayprotocol/relay-docs):

  • references/relay-kit/sdk/adapters.mdx — update

Draft:

> Replace: the `vmType` row in the interface table under `### What is an adapter anyway?`

| **vmType**                    | A string representing a supported vmType (`evm`  `svm`  `bvm`  `tvm` `lvm` `tonvm`)                                                   ||
> Insert after: the `[Lighter Adapter]` entry under `### What adapters are available out of the box?`

[TON Adapter](https://github.com/relayprotocol/relay-kit/tree/main/packages/relay-ton-wallet-adapter): This adapter gives the SDK the ability to submit transactions on the TON blockchain. The user's key stays in their wallet, so the adapter never signs — you pass a `sendTransaction` callback (for example wrapping Dynamic's TON connector or TonConnect UI) that signs and broadcasts the request, while the adapter handles request building and on-chain confirmation. Confirmation reads default to a public toncenter endpoint; pass your own `@ton/ton` `TonClient` or an `endpoint` via the optional `options` argument for production use. TON support requires the `@ton/core` and `@ton/ton` peer dependencies in addition to `viem` and `@relayprotocol/relay-sdk`.
> Insert after: the `Lighter` tab inside the `<CodeGroup>` under `### How can I use an adapter?` (before the closing `</CodeGroup>`)

```typescript TON
import { getClient, Execute, getQuote } from "@relayprotocol/relay-sdk"
import { adaptTonWallet } from '@relayprotocol/relay-ton-wallet-adapter'

// The user's key lives in their TON wallet, so the adapter never signs. You
// provide a sendTransaction callback that forwards the TonConnect-style request
// to your wallet provider (e.g. Dynamic's TON connector or tonConnectUI), signs
// + broadcasts it, and returns the result. The adapter accepts a signed
// external-message { boc } (what most TonConnect wallets return) or a
// { transactionHash }.
const adaptedWallet = adaptTonWallet(walletAddress, async (request) => {
  const { boc } = await wallet.sendTransaction(request)
  return { boc }
})

const options = ... // define this based on getQuote options

const quote = await getClient().actions.getQuote(options)

getClient().actions.execute({
  quote,
  wallet: adaptedWallet,
  onProgress: ({ steps, fees, breakdown, currentStep, currentStepItem, txHashes, details }) => {
    // custom handling
  },
  ...
})
```

Needs human input:

  • TON message signing (handleSignMessageStep) is intentionally not implemented (not used by deposit/bridge flows) and throws if invoked. The interface table marks handleSignMessageStep as required ✅; no change is proposed here, but a reviewer may want to add a short note that the TON adapter does not implement this step.

To publish as a draft PR in relayprotocol/relay-docs, reply on this PR with:

/publish-docs-pr

A separate workflow will open a draft PR attributed to you. Edit the draft freely before marking it ready for review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants