Skip to content

Commit

Permalink
feat: support ton chain (#1026)
Browse files Browse the repository at this point in the history
* feat: add basic ton provider

* feat: add ton connect to wallet

* feat: complete connect and disconnect v1

* feat: 添加了额外的钱包以及

* chore: update ton readme

* chore: add changeset

* feat: add ton transaction

* chore: update review code

* docs: 添加文档

* feat: flatten provider props

* feat: 添加ton钱包icon

* feat: 添加web3 json 文件

* docs: 更新 ton 的文档

* fix: wallet icon

* feat: update snapshot

* chore: update test file

* fix: ci error (#1036)

* chore(deps): bump wagmi from 2.10.5 to 2.10.9 (#1022)

Bumps [wagmi](https://github.com/wevm/wagmi/tree/HEAD/packages/react) from 2.10.5 to 2.10.9.
- [Release notes](https://github.com/wevm/wagmi/releases)
- [Changelog](https://github.com/wevm/wagmi/blob/main/packages/react/CHANGELOG.md)
- [Commits](https://github.com/wevm/wagmi/commits/[email protected]/packages/react)

---
updated-dependencies:
- dependency-name: wagmi
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix(test): coverage include files wrong (#1027)

* fix(test): coverage include files wrong

* Update vitest.config.mts

Co-authored-by: thinkasany <[email protected]>

* Update vitest.config.mts

* Update vitest.config.mts

* test: ignore coverage for some files

* chore: format

---------

Co-authored-by: thinkasany <[email protected]>

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: gin-lsl <[email protected]>

* chore: merge ci

* chore: update test

* docs: udate api docs

* chore: bump ts

* chore: update deps

* chore: update wallet icon

* fix: update icon deps

* chore: delete useless icons

* chore: casing promblem

* chore: update snapshot

* chore: delete useless file

* chore: delete useless file

* chore: delete useless file

* chore: add space

* chore: add space

* chore: add test

* feat: add okx for ton

* chore: update doc

* chore: resolve review issue

* chore: resolve review issue

* chore: update testfile

* Update packages/ton/package.json

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: thinkasany <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: gin-lsl <[email protected]>
Co-authored-by: 愚指导 <[email protected]>
  • Loading branch information
5 people authored Jul 29, 2024
1 parent d663c3b commit d49a4b8
Show file tree
Hide file tree
Showing 36 changed files with 1,389 additions and 412 deletions.
6 changes: 6 additions & 0 deletions .changeset/ten-elephants-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@ant-design/web3-ton': major
'@ant-design/web3': minor
---

feat: add ton chain
Empty file.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
"@ant-design/web3-icons": "workspace:*",
"@ant-design/web3-solana": "workspace:*",
"@ant-design/web3-wagmi": "workspace:*",
"@ant-design/web3-ton": "workspace:*",
"@solana/wallet-adapter-coinbase": "^0.1.19",
"@solana/wallet-adapter-trust": "^0.1.13",
"@tanstack/react-query": "^5.51.11",
Expand Down
5 changes: 5 additions & 0 deletions packages/ton/.fatherrc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { defineConfig } from 'father';

export default defineConfig({
extends: '../../.fatherrc.base.ts',
});
64 changes: 64 additions & 0 deletions packages/ton/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"name": "@ant-design/web3-ton",
"version": "0.0.0",
"main": "dist/lib/index.js",
"module": "dist/esm/index.js",
"typings": "dist/esm/index.d.ts",
"exports": {
"import": "./dist/esm/index.js",
"require": "./dist/lib/index.js",
"types": "./dist/esm/index.d.ts"
},
"sideEffects": false,
"files": [
"dist",
"CHANGELOG.md",
"README.md"
],
"keywords": [
"ant",
"component",
"components",
"design",
"framework",
"frontend",
"react",
"react-component",
"ui",
"web3",
"ton"
],
"homepage": "https://web3.ant.design",
"bugs": {
"url": "https://github.com/ant-design/ant-design-web3/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/ant-design/ant-design-web3"
},
"scripts": {
"dev": "father dev",
"build": "father build"
},
"dependencies": {
"@ant-design/web3-assets": "workspace:*",
"@ant-design/web3-common": "workspace:*"
},
"devDependencies": {
"father": "^4.4.4",
"typescript": "^5.5.2"
},
"publishConfig": {
"registry": "https://registry.npmjs.org",
"access": "public"
},
"peerDependencies": {
"@tonconnect/sdk": "^3.0.3"
},
"browserslist": [
"last 2 versions",
"Firefox ESR",
"> 1%",
"ie >= 11"
]
}
1 change: 1 addition & 0 deletions packages/ton/src/chains/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { CHAIN } from '@tonconnect/sdk';
1 change: 1 addition & 0 deletions packages/ton/src/hooks/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useTonConnector';
14 changes: 14 additions & 0 deletions packages/ton/src/hooks/useTonConnector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';

import { TonConnectorContext } from '../ton-provider/TonWeb3ConfigProvider';

export const useTonConnector = () => {
const provider = React.useContext(TonConnectorContext);
return {
connector: provider?.tonConnectSdk,
account: provider?.tonConnectSdk?.account,
tonSelectWallet: provider?.tonSelectWallet,
setTonSelectWallet: provider?.setTonSelectWallet,
connectConfig: provider?.connectConfig,
};
};
4 changes: 4 additions & 0 deletions packages/ton/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './ton-provider';
export * from './wallets';
export * from './chains';
export * from './hooks';
59 changes: 59 additions & 0 deletions packages/ton/src/ton-provider/TonConnectSdk.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import TonConnect, { CHAIN, type TonConnectOptions } from '@tonconnect/sdk';

export interface TonConnectSdkConfigType extends TonConnectOptions {
chain?: CHAIN;
}
class TonConnectSdk extends TonConnect {
private _api: string;
private _network: CHAIN;

constructor(options: TonConnectSdkConfigType) {
super({ manifestUrl: options?.manifestUrl });
this._api = '';
this._network = CHAIN.MAINNET;
this._switchNetwork(options.chain || this._network);
}

get network() {
return this._network;
}

set network(network: CHAIN) {
this._switchNetwork(network);
}

get api() {
return this._api;
}

private _switchNetwork(network: CHAIN) {
if (network === CHAIN.MAINNET) {
this._api = 'https://toncenter.com/api/v3';
} else {
this._api = 'https://testnet.toncenter.com/api/v3';
}
this._network = network;
}

async getBalance(url?: string) {
if (!this.account?.address && !url) return Promise.resolve(0n);
const queryUrl = url || `${this._api}/account?address=${this.account?.address}`;
return fetch(queryUrl, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then((res) => {
if (!res.ok) {
throw new Error('Failed to fetch balance');
}
return res.json();
})
.then((res) => {
return res.balance as bigint;
});
}
}

export default TonConnectSdk;
82 changes: 82 additions & 0 deletions packages/ton/src/ton-provider/TonWeb3ConfigProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React, { useEffect, type PropsWithChildren } from 'react';
import type { Locale } from '@ant-design/web3-common';
import type { CHAIN, TonConnectOptions, Wallet } from '@tonconnect/sdk';

import { TonWalletFactory } from '../wallets/factory';
import type { TonBasicWallet, TonWalletMetadata } from '../wallets/type';
import TonConfigProvider from './config-provider';
import TonConnectSdk, { type TonConnectSdkConfigType } from './TonConnectSdk';

interface TonConnectorContextProps {
tonConnectSdk: TonConnectSdk | null;
tonSelectWallet: Wallet | null;
setTonSelectWallet: (sdk: Wallet | null) => void;
connectConfig: TonConnectSdkConfigType;
}

export const TonConnectorContext = React.createContext<TonConnectorContextProps | null>(null);

export interface TonWeb3ConfigProviderProps extends TonConnectOptions {
locale?: Locale;
balance?: boolean;
wallets: TonWalletMetadata[];
chain?: CHAIN;
reconnect?: boolean;
}

export const TonWeb3ConfigProvider: React.FC<PropsWithChildren<TonWeb3ConfigProviderProps>> = ({
children,
...restProps
}) => {
const { balance, locale, wallets, chain, reconnect = true } = restProps;

const [tonConnectSdk, setTonConnectSdk] = React.useState<TonConnectSdk | null>(null);
const [tonSelectWallet, setTonSelectWallet] = React.useState<Wallet | null>(null);
const [tonWallets, setTonWallets] = React.useState<TonBasicWallet[]>([]);

useEffect(() => {
if (!tonConnectSdk) {
const tonSdk = new TonConnectSdk({ ...restProps, chain });
if (reconnect) {
tonSdk.restoreConnection();
}
tonSdk.onStatusChange((s) => {
setTonSelectWallet(s);
});
setTonConnectSdk(tonSdk);
}
}, [tonConnectSdk, restProps, reconnect, chain]);

React.useEffect(() => {
if (tonConnectSdk && wallets?.length) {
tonConnectSdk.getWallets().then((res) => {
const availableWallets = wallets.filter(
(w) => res.findIndex((t) => t.appName === w.key) >= 0,
);
setTonWallets(
availableWallets.map((w) => {
const tonBasicWallet = res.find((t) => t.appName === w.key)!;
return {
...w,
...tonBasicWallet,
};
}),
);
});
}
}, [wallets, tonConnectSdk]);

return (
<TonConnectorContext.Provider
value={{ tonConnectSdk, tonSelectWallet, setTonSelectWallet, connectConfig: restProps }}
>
<TonConfigProvider
wallets={tonWallets.map((w) => TonWalletFactory(w).create())}
balance={balance}
locale={locale}
>
{children}
</TonConfigProvider>
</TonConnectorContext.Provider>
);
};
47 changes: 47 additions & 0 deletions packages/ton/src/ton-provider/__tests__/balance.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest';

import { CHAIN } from '../../index';
import TonConnectSdk from '../TonConnectSdk';

global.fetch = vi.fn();
function createFetchResponse(data: any) {
return Promise.resolve({ ok: true, json: () => new Promise((resolve) => resolve(data)) });
}

describe('TonSdkWithMock', () => {
beforeEach(() => {
// @ts-ignore: vi.fn().mockReset
global.fetch.mockReset();
});

afterAll(() => {
vi.restoreAllMocks();
vi.resetModules();
});

it('has address', async () => {
vi.mock('@tonconnect/sdk', async () => {
const originModules = await vi.importActual('@tonconnect/sdk');
return {
...originModules,
default: class {
account = {
address: '123',
};
constructor() {
this.account = {
address: '124',
};
}
restoreConnection = () => {};
onStatusChange = () => {};
},
};
});
// @ts-ignore: vi.fn().mockResolvedValue
fetch.mockResolvedValue(createFetchResponse({ balance: '1000000000000' }));
const connector = new TonConnectSdk({ chain: CHAIN.TESTNET });
const balance = await connector.getBalance();
expect(balance).not.toBe('0');
});
});
Loading

0 comments on commit d49a4b8

Please sign in to comment.