-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/rf 2840 migrating tonconnect to hub #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next
Are you sure you want to change the base?
Changes from all commits
cbc0c57
32deffa
ea28386
2ccb6c1
8dddf18
7ee58a7
64f5f2b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "name": "@rango-dev/wallets-core/namespaces/ton", | ||
| "type": "module", | ||
| "main": "../../dist/namespaces/ton/mod.js", | ||
| "module": "../../dist/namespaces/ton/mod.js", | ||
| "types": "../../dist/namespaces/ton/mod.d.ts", | ||
| "sideEffects": false | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import type { TonActions } from './types.js'; | ||
|
|
||
| import { ActionBuilder } from '../../builders/action.js'; | ||
| import { intoConnectionFinished } from '../common/after.js'; | ||
| import { connectAndUpdateStateForSingleNetwork } from '../common/and.js'; | ||
| import { intoConnecting } from '../common/before.js'; | ||
|
|
||
| export const connect = () => | ||
| new ActionBuilder<TonActions, 'connect'>('connect') | ||
| .and(connectAndUpdateStateForSingleNetwork) | ||
| .before(intoConnecting) | ||
| .after(intoConnectionFinished); | ||
|
|
||
| export const canEagerConnect = () => | ||
| new ActionBuilder<TonActions, 'canEagerConnect'>('canEagerConnect'); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export const CAIP_NAMESPACE = 'tvm'; | ||
| export const CAIP_TON_CHAIN_ID = '-239'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| export * as utils from './utils.js'; | ||
| export * as builders from './builders.js'; | ||
|
|
||
| export type { ProviderAPI, TonActions } from './types.js'; | ||
| export { CAIP_NAMESPACE, CAIP_TON_CHAIN_ID } from './constants.js'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import type { Accounts } from '../../types/accounts.js'; | ||
| import type { | ||
| AutoImplementedActionsByRecommended, | ||
| CommonActions, | ||
| } from '../common/types.js'; | ||
|
|
||
| export interface TonActions | ||
| extends AutoImplementedActionsByRecommended, | ||
| CommonActions { | ||
| connect: () => Promise<Accounts>; | ||
| canEagerConnect: () => Promise<boolean>; | ||
| } | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| export type ProviderAPI = Record<string, any>; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import type { CaipAccount } from '../../types/accounts.js'; | ||
|
|
||
| import { AccountId } from 'caip'; | ||
|
|
||
| import { CAIP_NAMESPACE, CAIP_TON_CHAIN_ID } from './constants.js'; | ||
|
|
||
| export function formatAccountsToCAIP(accounts: string[]) { | ||
| return accounts.map( | ||
| (account) => | ||
| AccountId.format({ | ||
| address: account.toString(), | ||
| chainId: { | ||
| namespace: CAIP_NAMESPACE, | ||
| reference: CAIP_TON_CHAIN_ID, | ||
| }, | ||
| }) as CaipAccount | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,3 +1,29 @@ | ||||||||||||||||||||||||||
| # @rango-dev/provider-tonconnect | ||||||||||||||||||||||||||
| TonConnect Wallet integration for hub. | ||||||||||||||||||||||||||
| [Homepage](https://ton.org/) | [Docs](https://docs.ton.org/ecosystem/ton-connect/overview) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| TonConnect | ||||||||||||||||||||||||||
| More about implementation status can be found [here](../readme.md). | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ## Implementation notes/limitations | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #### ⚠️ Initialization | ||||||||||||||||||||||||||
| You should provide TonConnect configs in configs.walletOptions[WalletTypes.TON_CONNECT] (which equals configs.walletOptions.tonconnect) | ||||||||||||||||||||||||||
|
Comment on lines
+5
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix markdown accessibility/readability lint issues. Use descriptive link text (Line 5) and avoid heading-level jumps (Line 9). 🔧 Proposed doc fix-More about implementation status can be found [here](../readme.md).
+More about implementation status can be found in the [wallet providers README](../readme.md).
-#### ⚠️ Initialization
+### ⚠️ Initialization📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.22.0)[warning] 5-5: Link text should be descriptive (MD059, descriptive-link-text) [warning] 9-9: Heading levels should only increment by one level at a time (MD001, heading-increment) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ### Feature | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #### ❌ Switch Account | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Ton wallets don't emit account change events: https://github.com/ton-blockchain/ton-connect/blob/main/wallet-guidelines.md | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #### ⚠️ Disconnect | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Some Ton wallets like **Tonkeeper** don't emit disconnect events | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #### ⚠️ Init | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| We set **'installed'** to `true` on initialization even if we can't initialize the TonConnect instance. | ||||||||||||||||||||||||||
| Instead, we throw an error when the user tries to connect and we haven't initialized the TonConnect instance. | ||||||||||||||||||||||||||
|
Comment on lines
+24
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Logic error: The 'installed' property is hardcoded to true regardless of whether the TonConnect instance is successfully initialized. This violates the provider's availability invariant, causing the UI to display the wallet as available even when it is in an unusable state (e.g., due to missing or invalid configuration). Consequently, users will encounter unexpected errors when attempting to connect to a wallet that incorrectly claimed to be installed. We set **'installed'** to `true` only after the TonConnect instance is successfully initialized with the provided configuration.
If initialization fails or configuration is missing, **'installed'** remains `false` to prevent the UI from offering an unusable connection option.Prompt for LLMTalk to Kody by mentioning @kody Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction. |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| More wallet information can be found in [readme.md](../readme.md). | ||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| import type { Context, FunctionWithContext } from '@rango-dev/wallets-core'; | ||
| import type { TonConnectUI } from '@tonconnect/ui'; | ||
|
|
||
| import { actions as commonActions } from '@rango-dev/wallets-core/namespaces/common'; | ||
| import { | ||
| type TonActions, | ||
| type ProviderAPI as TonProviderAPI, | ||
| utils, | ||
| } from '@rango-dev/wallets-core/namespaces/ton'; | ||
|
|
||
| import { tonConnect, waitForConnection } from '../utils.js'; | ||
|
|
||
| export function connect( | ||
| getInstance: () => TonConnectUI | ||
| ): FunctionWithContext<TonActions['connect'], Context> { | ||
| return async () => { | ||
| const tonInstance = getInstance(); | ||
| const connectionRestored = await tonInstance.connectionRestored; | ||
| const { toUserFriendlyAddress } = tonConnect.getModule(); | ||
| let userFriendlyAddress: string; | ||
|
|
||
| if (connectionRestored && tonInstance.account?.address) { | ||
| userFriendlyAddress = toUserFriendlyAddress(tonInstance.account.address); | ||
| } else { | ||
| await tonInstance.openModal(); | ||
| const result = await waitForConnection(tonInstance); | ||
| userFriendlyAddress = toUserFriendlyAddress(result); | ||
| } | ||
|
|
||
| return utils.formatAccountsToCAIP([userFriendlyAddress]); | ||
| }; | ||
| } | ||
|
|
||
| export function disconnect( | ||
| getInstance: () => TonProviderAPI | ||
| ): FunctionWithContext<TonActions['disconnect'], Context> { | ||
| return async (context) => { | ||
| const tonInstance = getInstance(); | ||
| if (tonInstance.connected) { | ||
| await tonInstance.disconnect(); | ||
| } | ||
| commonActions.disconnect(context); | ||
| }; | ||
| } | ||
|
|
||
| export function canEagerConnect( | ||
| getInstance: () => TonProviderAPI | ||
| ): FunctionWithContext<TonActions['canEagerConnect'], Context> { | ||
| return async () => { | ||
| const tonConnectUI = getInstance() as TonConnectUI; | ||
| const connectionRestored = await tonConnectUI.connectionRestored; | ||
| return connectionRestored; | ||
| }; | ||
| } | ||
|
|
||
| export const tonActions = { connect, disconnect, canEagerConnect }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import type { ProviderMetadata } from '@rango-dev/wallets-core'; | ||
|
|
||
| import { WalletTypes } from '@rango-dev/wallets-shared'; | ||
| import { type BlockchainMeta, tonBlockchain } from 'rango-types'; | ||
|
|
||
| import getSigners from './signer.js'; | ||
| import { getInstanceOrThrow } from './utils.js'; | ||
|
|
||
| export const WALLET_ID = WalletTypes.TON_CONNECT; | ||
|
|
||
| export const metadata: ProviderMetadata = { | ||
| name: 'TON Connect', | ||
| icon: 'https://raw.githubusercontent.com/rango-exchange/assets/7fb19ed5d5019b4d6a41ce91b39cde64f86af4c6/wallets/tonconnect/icon.svg', | ||
| extensions: {}, | ||
| properties: [ | ||
| { | ||
| name: 'namespaces', | ||
| value: { | ||
| selection: 'single', | ||
| data: [ | ||
| { | ||
| label: 'Ton', | ||
| value: 'Ton', | ||
| id: 'TON', | ||
| getSupportedChains: (allBlockchains: BlockchainMeta[]) => | ||
| tonBlockchain(allBlockchains), | ||
| }, | ||
| ], | ||
| }, | ||
| }, | ||
| { | ||
| name: 'signers', | ||
| value: { | ||
| getSigners: async () => getSigners(getInstanceOrThrow()), | ||
| }, | ||
| }, | ||
| ], | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Namespace
initargs are forwarded but currently not consumed.runAll('init', args)passes per-namespace args, butwallets/core/src/hub/namespaces/namespace.tsdefinesinit()without parameters, so namespace init args are effectively dropped.🔧 Suggested follow-up change (outside this file)
🤖 Prompt for AI Agents
🧩 Analysis chain
🏁 Script executed:
Repository: RyukTheCoder/rango-client
Length of output: 7057
Bind namespace methods to preserve
thiscontext.Namespace methods are invoked detached from their instance. The
init(),state(), and all other methods in the Namespace class access private fields (e.g.,this.#initiated,this.#store) or call private methods (e.g.,this.#storeId(),this.#context()). Without proper binding,thiswill beundefined, causing runtime errors. Invoke with.call(namespace, ...).🔧 Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents