Skip to content

Commit

Permalink
feat: add ton connect provider
Browse files Browse the repository at this point in the history
  • Loading branch information
Ikari-Shinji-re committed Nov 20, 2024
1 parent aa6887c commit e1e2c58
Show file tree
Hide file tree
Showing 32 changed files with 373 additions and 13 deletions.
3 changes: 2 additions & 1 deletion examples/queue-manager-demo/src/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export const TREZOR_MANIFEST = {
appUrl: 'https://widget.rango.exchange/',
email: 'hi+trezorwidget@rango.exchange',
};

export const TON_CONNECT_MANIFEST_URL =
'https://raw.githubusercontent.com/rango-exchange/rango-types/main/assets/manifests/tonconnect-manifest.json';
let configs: Configs = {
API_KEY: RANGO_PUBLIC_API_KEY,
};
Expand Down
7 changes: 6 additions & 1 deletion examples/queue-manager-demo/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@ import React, { useEffect, useState } from 'react';
import { createRoot } from 'react-dom/client';

import { App } from './App';
import { TREZOR_MANIFEST, WC_PROJECT_ID } from './configs';
import {
TON_CONNECT_MANIFEST_URL,
TREZOR_MANIFEST,
WC_PROJECT_ID,
} from './configs';

const providers = allProviders({
walletconnect2: {
WC_PROJECT_ID: WC_PROJECT_ID,
},
trezorManifest: TREZOR_MANIFEST,
tonconnect: { manifestUrl: TON_CONNECT_MANIFEST_URL },
});

function AppContainer() {
Expand Down
7 changes: 6 additions & 1 deletion examples/wallets-adapter-demo/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ import { RangoClient } from 'rango-sdk';
import React, { useEffect, useState } from 'react';

import WalletsModal from './components/WalletsModal';
import { TREZOR_MANIFEST, WC_PROJECT_ID } from './constants';
import {
TON_CONNECT_MANIFEST_URL,
TREZOR_MANIFEST,
WC_PROJECT_ID,
} from './constants';

const providers = allProviders({
walletconnect2: {
WC_PROJECT_ID: WC_PROJECT_ID,
},
trezorManifest: TREZOR_MANIFEST,
tonconnect: { manifestUrl: TON_CONNECT_MANIFEST_URL },
});

export function App() {
Expand Down
2 changes: 2 additions & 0 deletions examples/wallets-adapter-demo/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ export const TREZOR_MANIFEST = {
appUrl: 'https://widget.rango.exchange/',
email: 'hi+trezorwidget@rango.exchange',
};
export const TON_CONNECT_MANIFEST_URL =
'https://raw.githubusercontent.com/rango-exchange/rango-types/main/assets/manifests/tonconnect-manifest.json';
7 changes: 6 additions & 1 deletion examples/wallets-demo/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@ import { RangoClient } from 'rango-sdk';
import React, { useEffect, useState } from 'react';

import List from './components/List';
import { TREZOR_MANIFEST, WC_PROJECT_ID } from './constants';
import {
TON_CONNECT_MANIFEST_URL,
TREZOR_MANIFEST,
WC_PROJECT_ID,
} from './constants';

const providers = allProviders({
walletconnect2: {
WC_PROJECT_ID: WC_PROJECT_ID,
},
trezorManifest: TREZOR_MANIFEST,
tonconnect: { manifestUrl: TON_CONNECT_MANIFEST_URL },
});

export function App() {
Expand Down
7 changes: 6 additions & 1 deletion examples/wallets-demo/src/components/List/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import { useWallets } from '@rango-dev/wallets-react';
import { sortWalletsBasedOnState } from '@rango-dev/wallets-shared';
import React from 'react';

import { TREZOR_MANIFEST, WC_PROJECT_ID } from '../../constants';
import {
TON_CONNECT_MANIFEST_URL,
TREZOR_MANIFEST,
WC_PROJECT_ID,
} from '../../constants';

import Item from './Item';

Expand All @@ -17,6 +21,7 @@ function List({ tokens }: { tokens: Token[] }) {
const providerTypes = allProviders({
walletconnect2: { WC_PROJECT_ID: WC_PROJECT_ID },
trezorManifest: TREZOR_MANIFEST,
tonconnect: { manifestUrl: TON_CONNECT_MANIFEST_URL },
}).map((p) => p.config.type);
const allWallets = sortWalletsBasedOnState(
providerTypes.map((type) => {
Expand Down
2 changes: 2 additions & 0 deletions examples/wallets-demo/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ export const TREZOR_MANIFEST = {
appUrl: 'https://widget.rango.exchange/',
email: 'hi+trezorwidget@rango.exchange',
};
export const TON_CONNECT_MANIFEST_URL =
'https://raw.githubusercontent.com/rango-exchange/rango-types/main/assets/manifests/tonconnect-manifest.json';

export const swaps = {
EVM: {
Expand Down
1 change: 1 addition & 0 deletions wallets/provider-all/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"@rango-dev/provider-taho": "^0.38.0",
"@rango-dev/provider-tokenpocket": "^0.38.0",
"@rango-dev/provider-tomo": "^0.5.0",
"@rango-dev/provider-tonconnect": "^0.1.0",
"@rango-dev/provider-mytonwallet": "0.23.0",
"@rango-dev/provider-trezor": "^0.5.0",
"@rango-dev/provider-tron-link": "^0.38.0",
Expand Down
19 changes: 19 additions & 0 deletions wallets/provider-all/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Environments as TonConnectEnvironment } from '@rango-dev/provider-tonconnect';
import type { Environments as TrezorEnvironments } from '@rango-dev/provider-trezor';
import type { Environments as WalletConnectEnvironments } from '@rango-dev/provider-walletconnect-2';
import type { ProviderInterface } from '@rango-dev/wallets-react';
Expand Down Expand Up @@ -31,6 +32,7 @@ import * as solflareSnap from '@rango-dev/provider-solflare-snap';
import * as taho from '@rango-dev/provider-taho';
import * as tokenpocket from '@rango-dev/provider-tokenpocket';
import * as tomo from '@rango-dev/provider-tomo';
import * as tonconnect from '@rango-dev/provider-tonconnect';
import * as trezor from '@rango-dev/provider-trezor';
import * as tronLink from '@rango-dev/provider-tron-link';
import * as trustwallet from '@rango-dev/provider-trustwallet';
Expand All @@ -44,6 +46,7 @@ interface Options {
walletconnect2: WalletConnectEnvironments;
selectedProviders?: (WalletType | ProviderInterface)[];
trezor?: TrezorEnvironments;
tonconnect?: TonConnectEnvironment;
}

export const allProviders = (options?: Options) => {
Expand Down Expand Up @@ -75,6 +78,21 @@ export const allProviders = (options?: Options) => {
}
}

if (
!isWalletExcluded(providers, {
type: WalletTypes.TON_CONNECT,
name: 'TON Connect',
})
) {
if (!!options?.tonconnect?.manifestUrl) {
tonconnect.init(options.tonconnect);
} else {
throw new Error(
'TON Connect has been included in your providers. Passing a Manifest URL is required. Make sure you are passing "manifestUrl".'
);
}
}

return [
safe,
defaultInjected,
Expand Down Expand Up @@ -110,5 +128,6 @@ export const allProviders = (options?: Options) => {
trezor,
solflare,
mytonwallet,
tonconnect,
];
};
3 changes: 2 additions & 1 deletion wallets/provider-mytonwallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"@rango-dev/wallets-shared": "^0.38.0",
"rango-types": "^0.1.74",
"@ton/core": "^0.59.0",
"@ton/crypto": "3.3.0"
"@ton/crypto": "3.3.0",
"@tonconnect/sdk": "^3.0.5"
},
"publishConfig": {
"access": "public"
Expand Down
36 changes: 36 additions & 0 deletions wallets/provider-tonconnect/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@rango-dev/provider-tonconnect",
"version": "0.1.0",
"license": "MIT",
"type": "module",
"source": "./src/index.ts",
"main": "./dist/index.js",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"typings": "dist/index.d.ts",
"files": [
"dist",
"src"
],
"scripts": {
"build": "node ../../scripts/build/command.mjs --path wallets/provider-tonconnect",
"ts-check": "tsc --declaration --emitDeclarationOnly -p ./tsconfig.json",
"clean": "rimraf dist",
"format": "prettier --write '{.,src}/**/*.{ts,tsx}'",
"lint": "eslint \"**/*.{ts,tsx}\" --ignore-path ../../.eslintignore"
},
"dependencies": {
"@rango-dev/wallets-shared": "^0.38.0",
"@ton/core": "^0.59.0",
"@ton/crypto": "3.3.0",
"@tonconnect/ui": "^2.0.9",
"rango-types": "^0.1.74"
},
"publishConfig": {
"access": "public"
}
}
3 changes: 3 additions & 0 deletions wallets/provider-tonconnect/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# @rango-dev/provider-tonconnect

TonConnect
42 changes: 42 additions & 0 deletions wallets/provider-tonconnect/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { TonConnectUI } from '@tonconnect/ui';

import { type Connect, Networks } from '@rango-dev/wallets-shared';
import { Address } from '@ton/core';

export const waitForConnection = async (
tonConnectUI: TonConnectUI
): ReturnType<Connect> => {
return new Promise((resolve, reject) => {
const unsubscribeStatusChange = tonConnectUI.onStatusChange(
(state) => {
const walletConnected = !!state?.account.address;

if (walletConnected) {
unsubscribeStatusChange();
resolve({
accounts: [parseAddress(state.account.address)],
chainId: Networks.TON,
});
}
},
(error) => {
unsubscribeStatusChange();
reject(error);
}
);

const unsubscribeModalStateChange = tonConnectUI.onModalStateChange(
(modalState) => {
if (modalState.closeReason === 'action-cancelled') {
unsubscribeStatusChange();
unsubscribeModalStateChange();
reject(new Error('The action was canceled by the user'));
}
}
);
});
};

export function parseAddress(rawAddress: string): string {
return Address.parse(rawAddress).toString({ bounceable: false });
}
86 changes: 86 additions & 0 deletions wallets/provider-tonconnect/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import type { Environments } from './types.js';
import type {
CanEagerConnect,
CanSwitchNetwork,
Connect,
Disconnect,
GetInstance,
WalletInfo,
} from '@rango-dev/wallets-shared';
import type { BlockchainMeta, SignerFactory } from 'rango-types';

import { Networks, WalletTypes } from '@rango-dev/wallets-shared';
import { TonConnectUI } from '@tonconnect/ui';
import { tonBlockchain } from 'rango-types';

import { parseAddress, waitForConnection } from './helpers.js';
import signer from './signer.js';

let envs: Environments = {
manifestUrl: '',
};

const WALLET = WalletTypes.TON_CONNECT;

export const config = {
type: WALLET,
};

export type { Environments };

export const init = (environments: Environments) => {
envs = environments;
};

let instance: TonConnectUI | null = null;

export const getInstance: GetInstance = () => {
if (!instance) {
instance = new TonConnectUI(envs);
}
return instance;
};

export const connect: Connect = async ({ instance }) => {
const tonConnectUI: TonConnectUI = instance;
const connectionRestored = await tonConnectUI.connectionRestored;

if (connectionRestored && tonConnectUI.account?.address) {
const currentWalletAccount = parseAddress(tonConnectUI.account.address);
return { accounts: [currentWalletAccount], chainId: Networks.TON };
}

await tonConnectUI.openModal();
const result = await waitForConnection(tonConnectUI);

return result;
};

export const canEagerConnect: CanEagerConnect = async ({ instance }) => {
const tonConnectUI = instance as TonConnectUI;
const connectionRestored = await tonConnectUI.connectionRestored;
return connectionRestored;
};

export const canSwitchNetworkTo: CanSwitchNetwork = () => false;

export const getSigners: (provider: TonConnectUI) => Promise<SignerFactory> =
signer;

export const getWalletInfo: (allBlockChains: BlockchainMeta[]) => WalletInfo = (
allBlockChains
) => {
const ton = tonBlockchain(allBlockChains);
return {
name: 'TON Connect',
img: 'https://raw.githubusercontent.com/rango-exchange/assets/7fb19ed5d5019b4d6a41ce91b39cde64f86af4c6/wallets/tonconnect/icon.svg',
installLink: '',
color: '#fff',
supportedChains: ton,
};
};

export const disconnect: Disconnect = async ({ instance }) => {
const tonConnectUI = instance as TonConnectUI;
await tonConnectUI.disconnect();
};
13 changes: 13 additions & 0 deletions wallets/provider-tonconnect/src/signer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { TonConnectUI } from '@tonconnect/ui';
import type { SignerFactory } from 'rango-types';

import { DefaultSignerFactory, TransactionType as TxType } from 'rango-types';

export default async function getSigners(
provider: TonConnectUI
): Promise<SignerFactory> {
const signers = new DefaultSignerFactory();
const { CustomTonSigner } = await import('./ton-signer.js');
signers.registerSigner(TxType.TON, new CustomTonSigner(provider));
return signers;
}
29 changes: 29 additions & 0 deletions wallets/provider-tonconnect/src/ton-signer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { TonConnectUI } from '@tonconnect/ui';
import type { GenericSigner, TonTransaction } from 'rango-types';

import { Cell } from '@ton/core';
import { CHAIN } from '@tonconnect/ui';
import { SignerError } from 'rango-types';

export class CustomTonSigner implements GenericSigner<TonTransaction> {
private provider: TonConnectUI;

constructor(provider: TonConnectUI) {
this.provider = provider;
}

async signMessage(): Promise<string> {
throw SignerError.UnimplementedError('signMessage');
}

async signAndSendTx(tx: TonTransaction): Promise<{ hash: string }> {
const { blockChain, type, ...txObjectForSign } = tx;
const result = await this.provider.sendTransaction({
...txObjectForSign,
network: CHAIN.MAINNET,
});

const hash = Cell.fromBase64(result.boc).hash().toString('hex');
return { hash };
}
}
3 changes: 3 additions & 0 deletions wallets/provider-tonconnect/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface Environments extends Record<string, string | undefined> {
manifestUrl: string;
}
Loading

0 comments on commit e1e2c58

Please sign in to comment.