Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
220e846
feat: update intent handling functionality in demo wallet
nikdim03 Mar 13, 2026
a8d4354
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 13, 2026
0f9b200
feat: rename transaction draft event to transaction intent for clarity
nikdim03 Mar 13, 2026
fe27fbf
fix: fix lint
nikdim03 Mar 13, 2026
844de6a
fix: fix quality
nikdim03 Mar 13, 2026
3fe3925
fix: remove unused parameter from setupPassword test
nikdim03 Mar 13, 2026
91f2e89
fix: fix lint
nikdim03 Mar 13, 2026
190486e
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 13, 2026
4d0b082
feat: update password helper text to reflect new requirements
nikdim03 Mar 13, 2026
cef4a42
chore: revert unrelated files
nikdim03 Mar 13, 2026
ff8e3e2
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 13, 2026
519d956
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 13, 2026
123ae3f
refactor: update buildInlineUrl to use method and params structure in…
nikdim03 Mar 13, 2026
66313a7
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 13, 2026
fb4f2a6
fix: enhance error handling for action URL response to ensure valid JSON
nikdim03 Mar 13, 2026
d42aacb
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 13, 2026
8edb973
fix: lint
nikdim03 Mar 13, 2026
47ad555
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 13, 2026
2c878c8
feat: add new event types and draft intents to EventStore and wallet …
nikdim03 Mar 13, 2026
6d09280
feat: update intent origin and event types to include 'connectedBridg…
nikdim03 Mar 13, 2026
58c1ff1
feat: add handling for bridge-delivered draft events and enhance Inte…
nikdim03 Mar 13, 2026
f777213
feat: route draft events directly via event emitter for existing sess…
nikdim03 Mar 13, 2026
bd4c4a1
feat: add RawBridgeEvent type import to TonWalletKit
nikdim03 Mar 13, 2026
09da596
feat: update getTonConnectFeatures to include intent features and adj…
nikdim03 Mar 13, 2026
14bebfb
feat: add SignMessage and related intent features to WalletV4R2 and W…
nikdim03 Mar 13, 2026
175cd72
fix: use correct wire response format for signMsgDraft (internal_boc)
nikdim03 Mar 15, 2026
8c3c224
fix: pass deliveryMode to sendBatchResponse so signMsgDraft returns i…
nikdim03 Mar 15, 2026
8ab8734
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 16, 2026
23e6cb4
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 16, 2026
a8768d9
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 16, 2026
81584c5
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 16, 2026
333b5f2
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 16, 2026
70d8f09
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 16, 2026
5872c52
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 16, 2026
0e2b927
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 16, 2026
9a53572
feat: add activeWalletId prop to IntentRequestModal and BatchedIntent…
nikdim03 Mar 16, 2026
0613837
Merge branch 'feature/ton-359-new-intent-api-design' into feature/ton…
nikdim03 Mar 17, 2026
3736b69
remove stale eslint-disable comment in getTonConnectFeatures
nikdim03 Mar 17, 2026
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
531 changes: 531 additions & 0 deletions apps/demo-wallet/src/components/IntentRequestModal.tsx

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions apps/demo-wallet/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export { SettingsDropdown } from './SettingsDropdown';
export { ProtectedRoute } from './ProtectedRoute';
export { RecentTransactions } from './RecentTransactions';
export { SignDataRequestModal } from './SignDataRequestModal';
export { IntentRequestModal, BatchedIntentRequestModal } from './IntentRequestModal';
export { TraceRow } from './TraceRow';
export { TransactionRequestModal } from './TransactionRequestModal';
export { WalletPreview } from './WalletPreview';
Expand Down
85 changes: 74 additions & 11 deletions apps/demo-wallet/src/pages/WalletDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@

import React, { useState, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { useWallet, useWalletKit, useTonConnect, useTransactionRequests, useSignDataRequests } from '@demo/wallet-core';
import {
useWallet,
useWalletKit,
useTonConnect,
useTransactionRequests,
useSignDataRequests,
useIntents,
} from '@demo/wallet-core';

import {
Layout,
Expand All @@ -17,6 +24,8 @@ import {
ConnectRequestModal,
TransactionRequestModal,
SignDataRequestModal,
IntentRequestModal,
BatchedIntentRequestModal,
DisconnectNotifications,
NftsCard,
RecentTransactions,
Expand Down Expand Up @@ -62,10 +71,33 @@ export const WalletDashboard: React.FC = () => {
const { pendingTransactionRequest, isTransactionModalOpen } = useTransactionRequests();
const { pendingSignDataRequest, isSignDataModalOpen, approveSignDataRequest, rejectSignDataRequest } =
useSignDataRequests();
const {
pendingIntentEvent,
pendingBatchedIntentEvent,
isIntentModalOpen,
isBatchedIntentModalOpen,
handleIntentUrl,
isIntentUrl,
approveIntent,
rejectIntent,
approveBatchedIntent,
rejectBatchedIntent,
} = useIntents();
const { error } = useTonWallet();

// Use the paste handler hook
usePasteHandler(handleTonConnectUrl);
// Use the paste handler hook — route intent URLs to handleIntentUrl
const handlePastedUrl = useCallback(
async (url: string) => {
if (isIntentUrl(url)) {
log.info('Detected pasted intent URL, routing to intent handler');
await handleIntentUrl(url);
} else {
await handleTonConnectUrl(url);
}
},
[isIntentUrl, handleIntentUrl, handleTonConnectUrl],
);
usePasteHandler(handlePastedUrl);

const handleRefreshBalance = useCallback(async () => {
setIsRefreshing(true);
Expand Down Expand Up @@ -93,17 +125,22 @@ export const WalletDashboard: React.FC = () => {
const handleConnectDApp = useCallback(async () => {
if (!tonConnectUrl.trim()) return;

const url = tonConnectUrl.trim();
setIsConnecting(true);
try {
await handleTonConnectUrl(tonConnectUrl.trim());
if (isIntentUrl(url)) {
log.info('Detected intent URL, routing to intent handler');
await handleIntentUrl(url);
} else {
await handleTonConnectUrl(url);
}
setTonConnectUrl('');
} catch (err) {
log.error('Failed to connect to dApp:', err);
// TODO: Show error message to user
log.error('Failed to process URL:', err);
} finally {
setIsConnecting(false);
}
}, [tonConnectUrl, handleTonConnectUrl]);
}, [tonConnectUrl, handleTonConnectUrl, isIntentUrl, handleIntentUrl]);

const handleTestDisconnectAll = useCallback(async () => {
if (!walletKit) return;
Expand Down Expand Up @@ -286,18 +323,18 @@ export const WalletDashboard: React.FC = () => {
<NftsCard />

{/* TON Connect URL Input */}
<Card title="Connect to dApp">
<Card title="Connect to dApp / Handle Intent">
<div className="space-y-4">
<div>
<label htmlFor="tonconnect-url" className="block text-sm font-medium text-gray-700 mb-2">
Paste TON Connect Link
Paste TON Connect or Intent Link
</label>
<textarea
data-testid="tonconnect-url"
id="tonconnect-url"
rows={3}
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 resize-none text-black"
placeholder="tc://... or ton://... or https://..."
placeholder="tc://... or ton://... or https://... or intent URL"
value={tonConnectUrl}
onChange={(e) => setTonConnectUrl(e.target.value)}
/>
Expand All @@ -309,7 +346,9 @@ export const WalletDashboard: React.FC = () => {
disabled={!tonConnectUrl.trim() || isConnecting}
className="w-full"
>
Connect to dApp
{tonConnectUrl.trim() && isIntentUrl(tonConnectUrl.trim())
? 'Process Intent'
: 'Connect to dApp'}
</Button>
</div>
</Card>
Expand Down Expand Up @@ -382,6 +421,30 @@ export const WalletDashboard: React.FC = () => {
onReject={rejectSignDataRequest}
/>
)}

{/* Intent Request Modal */}
{pendingIntentEvent && (
<IntentRequestModal
event={pendingIntentEvent}
savedWallets={savedWallets}
activeWalletId={activeWallet?.kitWalletId}
isOpen={isIntentModalOpen}
onApprove={approveIntent}
onReject={rejectIntent}
/>
)}

{/* Batched Intent Request Modal */}
{pendingBatchedIntentEvent && (
<BatchedIntentRequestModal
batch={pendingBatchedIntentEvent}
savedWallets={savedWallets}
activeWalletId={activeWallet?.kitWalletId}
isOpen={isBatchedIntentModalOpen}
onApprove={approveBatchedIntent}
onReject={rejectBatchedIntent}
/>
)}
</Layout>
);
};
24 changes: 24 additions & 0 deletions demo/wallet-core/src/hooks/useWalletStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,27 @@ export const useSwap = () => {
})),
);
};

/**
* Hook for Intent state and actions
*/
export const useIntents = () => {
return useWalletStore(
useShallow((state) => ({
pendingIntentEvent: state.intent.pendingIntentEvent,
pendingBatchedIntentEvent: state.intent.pendingBatchedIntentEvent,
isIntentModalOpen: state.intent.isIntentModalOpen,
isBatchedIntentModalOpen: state.intent.isBatchedIntentModalOpen,
intentResult: state.intent.intentResult,
intentError: state.intent.intentError,
handleIntentUrl: state.handleIntentUrl,
isIntentUrl: state.isIntentUrl,
approveIntent: state.approveIntent,
rejectIntent: state.rejectIntent,
approveBatchedIntent: state.approveBatchedIntent,
rejectBatchedIntent: state.rejectBatchedIntent,
closeIntentModal: state.closeIntentModal,
closeBatchedIntentModal: state.closeBatchedIntentModal,
})),
);
};
2 changes: 2 additions & 0 deletions demo/wallet-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export {
useNfts,
useJettons,
useSwap,
useIntents,
} from './hooks/useWalletStore';
export { useFormattedTonBalance, useFormattedAmount } from './hooks/useFormattedBalance';
export { useWalletInitialization } from './hooks/useWalletInitialization';
Expand All @@ -42,6 +43,7 @@ export type {
WalletCoreSlice,
WalletManagementSlice,
TonConnectSlice,
IntentSlice,
JettonsSlice,
NftsSlice,
SwapSlice,
Expand Down
24 changes: 8 additions & 16 deletions demo/wallet-core/src/store/createWalletStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { createTonConnectSlice } from './slices/tonConnectSlice';
import { createJettonsSlice } from './slices/jettonsSlice';
import { createNftsSlice } from './slices/nftsSlice';
import { createSwapSlice } from './slices/swapSlice';
import { createIntentSlice } from './slices/intentSlice';
import type { AppState } from '../types/store';
import type { StorageAdapter } from '../adapters/storage/types';
import type { WalletKitConfig } from '../types/wallet';
Expand Down Expand Up @@ -141,6 +142,9 @@ export function createWalletStore(options: CreateWalletStoreOptions = {}) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
...createSwapSlice(...a),
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
...createIntentSlice(...a),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
})) as unknown as any,
{
Expand Down Expand Up @@ -232,29 +236,17 @@ export function createWalletStore(options: CreateWalletStoreOptions = {}) {
state.clearExpiredRequests();
}

// Resume processing if there are queued requests
// if (
// state.tonConnect.requestQueue.items.length > 0 &&
// !state.tonConnect.requestQueue.isProcessing &&
// state.processNextRequest
// ) {
// log.info('Resuming queue processing after rehydration');
// state.processNextRequest();
// }

const processTimeoutCallback = () => {
// Resume processing if there are queued requests after a short delay
setTimeout(() => {
if (
state.tonConnect.requestQueue.items.length > 0 &&
!state.tonConnect.requestQueue.isProcessing &&
state.processNextRequest
) {
log.info('Calling processNextRequest after timeout');
log.info('Resuming queue processing after rehydration');
state.processNextRequest();
}
setTimeout(() => processTimeoutCallback(), 1000);
};
processTimeoutCallback();
// setTimeout(() => {}, 1000);
}, 100);
},
},
),
Expand Down
Loading
Loading