Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/appkit-minter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"typecheck": "tsc --noEmit -p tsconfig.app.json"
},
"dependencies": {
"@tac/appkit-provider": "workspace:*",
"@ston-fi/omniston-sdk": "^0.7.9",
"@tailwindcss/vite": "^4.2.2",
"@ton/appkit": "workspace:*",
Expand Down
9 changes: 8 additions & 1 deletion apps/appkit-minter/src/core/configs/app-kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
import { DeDustSwapProvider } from '@ton/appkit/swap/dedust';
import { OmnistonSwapProvider } from '@ton/appkit/swap/omniston';
import { createTonstakersProvider } from '@ton/appkit/staking/tonstakers';
import { Network as TacNetwork } from '@tonappchain/sdk';
import { createTacProvider } from '@tac/appkit-provider';

import { ENV_TON_API_KEY_TESTNET, ENV_TON_API_KEY_MAINNET } from '@/core/configs/env';

Expand Down Expand Up @@ -48,7 +50,12 @@ export const appKit = new AppKit({
},
}),
],
providers: [new DeDustSwapProvider(), new OmnistonSwapProvider(), createTonstakersProvider({})],
providers: [
new DeDustSwapProvider(),
new OmnistonSwapProvider(),
createTonstakersProvider({}),
createTacProvider({ network: TacNetwork.TESTNET }),
],
});

// TODO: replace in normal config
Expand Down
53 changes: 53 additions & 0 deletions apps/appkit-minter/src/features/tac/components/tac-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* Copyright (c) TonTech.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

import { useState } from 'react';
import type { FC } from 'react';
import { useSmartAccountAddress } from '@tac/appkit-provider';

import { Card } from '@/core/components';

export const TacCard: FC = () => {
const [applicationAddress, setApplicationAddress] = useState('');

const { data: smartAccountAddress, isLoading, isError, error } = useSmartAccountAddress(applicationAddress);

return (
<Card title="TAC Smart Account">
<div className="flex flex-col gap-3">
<div>
<label
className="mb-1 block text-sm font-medium text-muted-foreground"
htmlFor="tac-application-address"
>
EVM Application Address
</label>
<input
id="tac-application-address"
type="text"
value={applicationAddress}
onChange={(e) => setApplicationAddress(e.target.value)}
placeholder="0x..."
className="w-full rounded-lg border border-border bg-input px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-ring focus:ring-2 focus:ring-ring"
/>
</div>

<div className="space-y-1 rounded-lg border border-border bg-muted px-3 py-2 text-sm">
<div className="flex justify-between gap-2">
<span className="text-muted-foreground">Smart Account Address</span>
<span className="font-medium text-foreground">
{isLoading && '…'}
{isError && <span className="text-destructive">{error?.message ?? '—'}</span>}
{!isLoading && !isError && (smartAccountAddress ?? '—')}
</span>
</div>
</div>
</div>
</Card>
);
};
9 changes: 9 additions & 0 deletions apps/appkit-minter/src/features/tac/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Copyright (c) TonTech.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

export * from './components/tac-card';
2 changes: 2 additions & 0 deletions apps/appkit-minter/src/pages/minter-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { Card, Layout } from '@/core/components';
import { SwapButton } from '@/features/swap';
import { StakingCard } from '@/features/staking';
import { SignMessageCard } from '@/features/signing';
import { TacCard } from '@/features/tac';

export const MinterPage: React.FC = () => {
const [wallet] = useSelectedWallet();
Expand Down Expand Up @@ -53,6 +54,7 @@ export const MinterPage: React.FC = () => {
</Card>

<StakingCard />
<TacCard />
</div>
)}
</div>
Expand Down
24 changes: 24 additions & 0 deletions demo/examples/src/appkit/actions/providers/get-custom-provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright (c) TonTech.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

import type { AppKit, CustomProvider } from '@ton/appkit';
import { getCustomProvider } from '@ton/appkit';

interface TacProvider extends CustomProvider {
sendCrossChainTransaction: (params: unknown) => Promise<void>;
}

export const getCustomProviderExample = (appKit: AppKit) => {
// SAMPLE_START: GET_CUSTOM_PROVIDER
const tac = getCustomProvider<TacProvider>(appKit, { id: 'tac' });

if (tac) {
console.log('TAC provider is available');
}
// SAMPLE_END: GET_CUSTOM_PROVIDER
};
44 changes: 44 additions & 0 deletions demo/examples/src/appkit/actions/providers/providers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Copyright (c) TonTech.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { AppKit } from '@ton/appkit';
import { Network } from '@ton/walletkit';

import { getCustomProviderExample } from './get-custom-provider';

describe('Provider Actions Examples (Integration)', () => {
let appKit: AppKit;
let consoleSpy: ReturnType<typeof vi.spyOn>;

beforeEach(() => {
vi.clearAllMocks();
consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});

appKit = new AppKit({
networks: { [Network.mainnet().chainId]: {} },
});
});

afterEach(() => {
consoleSpy.mockRestore();
});

describe('getCustomProviderExample', () => {
it('should log when custom provider is available', () => {
appKit.registerProvider({ providerId: 'tac', type: 'custom' as const });
getCustomProviderExample(appKit);
expect(consoleSpy).toHaveBeenCalledWith('TAC provider is available');
});

it('should not log when provider is not registered', () => {
getCustomProviderExample(appKit);
expect(consoleSpy).not.toHaveBeenCalled();
});
});
});
52 changes: 52 additions & 0 deletions demo/examples/src/appkit/hooks/providers/providers.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Copyright (c) TonTech.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

/* eslint-disable @typescript-eslint/no-explicit-any */

import { render, screen, cleanup } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';

import { createWrapper } from '../../../__tests__/test-utils';
import { UseCustomProviderExample } from './use-custom-provider';

describe('Provider Hooks Examples', () => {
let mockAppKit: any;

beforeEach(() => {
cleanup();
vi.clearAllMocks();

mockAppKit = {
emitter: { on: vi.fn(() => () => {}), off: vi.fn() },
connectors: [],
customProvidersManager: { getProvider: vi.fn().mockReturnValue(undefined) },
};
});

afterEach(() => {
cleanup();
});

describe('UseCustomProviderExample', () => {
it('should show not registered message when provider is absent', () => {
render(<UseCustomProviderExample />, { wrapper: createWrapper(mockAppKit) });
expect(screen.getByText('TAC provider not registered')).toBeDefined();
});

it('should show ready message when provider is registered', () => {
mockAppKit.customProvidersManager.getProvider = vi.fn().mockReturnValue({
providerId: 'tac',
type: 'custom',
sendCrossChainTransaction: vi.fn(),
});

render(<UseCustomProviderExample />, { wrapper: createWrapper(mockAppKit) });
expect(screen.getByText('TAC provider is ready')).toBeDefined();
});
});
});
26 changes: 26 additions & 0 deletions demo/examples/src/appkit/hooks/providers/use-custom-provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Copyright (c) TonTech.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

import type { CustomProvider } from '@ton/appkit';
import { useCustomProvider } from '@ton/appkit-react';

interface TacProvider extends CustomProvider {
sendCrossChainTransaction: (params: unknown) => Promise<void>;
}

export const UseCustomProviderExample = () => {
// SAMPLE_START: USE_CUSTOM_PROVIDER
const tac = useCustomProvider<TacProvider>('tac');

if (!tac) {
return <div>TAC provider not registered</div>;
}

return <div>TAC provider is ready</div>;
// SAMPLE_END: USE_CUSTOM_PROVIDER
};
14 changes: 14 additions & 0 deletions packages/appkit-react/docs/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -985,4 +985,18 @@ return (
);
```

### `useCustomProvider`

Hook to get a registered custom provider by id.

```tsx
const tac = useCustomProvider<TacProvider>('tac');

if (!tac) {
return <div>TAC provider not registered</div>;
}

return <div>TAC provider is ready</div>;
```


Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright (c) TonTech.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

import { getCustomProvider } from '@ton/appkit';
import type { CustomProvider } from '@ton/appkit';

import { useAppKit } from '../../../hooks/use-app-kit';

/**
* Hook to get a registered custom provider by id.
*/
export const useCustomProvider = <T extends CustomProvider = CustomProvider>(id: string): T | undefined => {
const appKit = useAppKit();
return getCustomProvider<T>(appKit, { id });
};
9 changes: 9 additions & 0 deletions packages/appkit-react/src/features/providers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Copyright (c) TonTech.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

export { useCustomProvider } from './hooks/use-custom-provider';
1 change: 1 addition & 0 deletions packages/appkit-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ export * from './features/wallets';
export * from './features/swap';
export * from './features/signing';
export * from './features/staking';
export * from './features/providers';
55 changes: 55 additions & 0 deletions packages/appkit-tac/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"name": "@tac/appkit-provider",
"version": "0.0.1",
"description": "TAC cross-chain provider for @ton/appkit",
"repository": {
"type": "git",
"url": "https://github.com/ton-connect/kit"
},
"sideEffects": false,
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"types": "dist/cjs/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/cjs/index.d.ts",
"default": "./dist/cjs/index.js"
}
}
},
"scripts": {
"build": "pnpm build:clean && pnpm build:cjs && pnpm build:esm",
"build:clean": "rimraf dist",
"build:esm": "tsc -p tsconfig.json",
"build:cjs": "tsc -p tsconfig.cjs.json",
"quality": "pnpm typecheck",
"typecheck": "tsc --noEmit",
"clean": "rimraf .turbo dist node_modules"
},
"dependencies": {
"@ton/appkit": "workspace:*",
"@ton/appkit-react": "workspace:*"
},
"peerDependencies": {
"@tanstack/react-query": ">=5.0.0",
"@tonappchain/sdk": ">=0.7.0",
"react": ">=18.0.0"
},
"devDependencies": {
"@tanstack/react-query": "catalog:",
"@tonappchain/sdk": "^0.7.2",
"@types/react": "catalog:",
"react": "catalog:",
"rimraf": "^6.0.1",
"typescript": "~5.9.3"
},
"keywords": [],
"author": "",
"license": "MIT",
"packageManager": "pnpm@10.15.0"
}
Loading
Loading