Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
db683a5
feat: implement intent API for WalletKit
nikdim03 Feb 23, 2026
807f176
fix: align intent API with TonConnect spec
nikdim03 Feb 23, 2026
dc32a9e
feat: add support for object storage and trace ID propagation
nikdim03 Feb 25, 2026
d1eeb77
feat: improve type definitions & model generation
nikdim03 Feb 25, 2026
d8408b2
fix: unwrap { type, value } event wrapper in bridge approve/reject me…
nikdim03 Feb 25, 2026
d4ee71a
feat: update address type to UserFriendlyAddress in IntentSignDataRes…
nikdim03 Feb 26, 2026
630a663
refactor: simplify intent API methods and improve type handling
nikdim03 Feb 26, 2026
9911d08
refactor: fix lint
nikdim03 Feb 26, 2026
5b6b794
test: add unit tests for IntentHandler and IntentParser
nikdim03 Feb 26, 2026
c502e40
refactor: fix lint
nikdim03 Feb 26, 2026
0c5b9f2
feat: add approveBatchedIntent and related functionality for handling…
nikdim03 Feb 26, 2026
16952ca
refactor: remove processConnectAfterIntent and related connect reques…
nikdim03 Feb 26, 2026
ed14b6c
feat: enhance approveBatchedIntent to handle signData items and updat…
nikdim03 Feb 27, 2026
dce87ec
feat: update getSignedSendTransaction to support internal message sig…
nikdim03 Feb 27, 2026
6d63d3e
refactor: fix lint
nikdim03 Feb 27, 2026
e1c7d1e
feat: refactor intent models to flat interface unions
nikdim03 Mar 6, 2026
51492c8
feat: update intent API to use 'txDraft' and 'signMsgDraft' terminolo…
nikdim03 Mar 13, 2026
74266fb
feat: rename intent approval methods to use 'Draft' terminology for c…
nikdim03 Mar 13, 2026
6d2313f
feat: enhance isIntentUrl method to support new URL format and pre-in…
nikdim03 Mar 13, 2026
6209fc8
feat: refactor intent request types and validation
nikdim03 Mar 13, 2026
5da4e79
fix: lint
nikdim03 Mar 13, 2026
b607ff8
refactor: update buildInlineUrl to use method and params structure in…
nikdim03 Mar 13, 2026
b081f97
feat: implement action intent handling with transaction and signData …
nikdim03 Mar 13, 2026
95438ea
fix: enhance error handling for action URL response to ensure valid JSON
nikdim03 Mar 13, 2026
3159514
feat: implement payload decryption using NaCl crypto_box with ephemer…
nikdim03 Mar 13, 2026
b1f5b1c
fix: lint
nikdim03 Mar 13, 2026
7d54d81
fix: remove redundant retry mechanism in transaction emulation
nikdim03 Mar 13, 2026
3fd48c1
Revert "fix: remove redundant retry mechanism in transaction emulation"
nikdim03 Mar 13, 2026
b84d3cb
feat: add support for https universal link scheme in IntentParser
nikdim03 Mar 13, 2026
7a7c6e4
feat: add new event types and draft intents to EventStore and wallet …
nikdim03 Mar 13, 2026
c1291f3
feat: update intent origin and event types to include 'connectedBridg…
nikdim03 Mar 13, 2026
8edad0a
feat: add handling for bridge-delivered draft events and enhance Inte…
nikdim03 Mar 13, 2026
b2046cc
feat: route draft events directly via event emitter for existing sess…
nikdim03 Mar 13, 2026
b173e8d
feat: add RawBridgeEvent type import to TonWalletKit
nikdim03 Mar 13, 2026
cbad602
feat: add SignMessage and related intent features to WalletV4R2 and W…
nikdim03 Mar 13, 2026
a606961
fix: use correct wire response format for signMsgDraft (internal_boc)
nikdim03 Mar 15, 2026
44a59fb
fix: pass deliveryMode to sendBatchResponse so signMsgDraft returns i…
nikdim03 Mar 15, 2026
ee1b5a1
fix: fix quality
nikdim03 Mar 13, 2026
2fbf8c0
refactor: rename approveTransactionIntent/approveActionIntent to Draf…
nikdim03 Mar 16, 2026
21cddde
fix: cast intent features to bypass outdated protocol types
nikdim03 Mar 16, 2026
a4b515e
refactor: clean up intent API — remove dead code, fix bugs, deduplicate
nikdim03 Mar 16, 2026
8e6ce7a
fix: restore removeEvent, fix IntentParser.spec.ts formatting
nikdim03 Mar 16, 2026
48b09a9
fix: remove intent features from adapters to fix e2e connect validation
nikdim03 Mar 16, 2026
0499ad3
refactor: update intent API types and methods for consistency
nikdim03 Mar 16, 2026
e59f703
Add type:'batched' discriminant to BatchedIntentEvent
nikdim03 Mar 16, 2026
4b48674
Filter intent features from DeviceInfo in TonConnect connect handshake
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
21 changes: 20 additions & 1 deletion apps/demo-wallet/src/utils/walletManifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,24 @@ export function getTonConnectFeatures(): Feature[] {
name: 'SignData',
types: ['text', 'binary', 'cell'],
},
];
// Intent features (new in protocol — cast until @tonconnect/protocol types are updated)
{
name: 'SignMessage',
},
{
name: 'SendTransactionDraft',
types: ['ton', 'jetton', 'nft'],
},
{
name: 'SignMessageDraft',
types: ['ton', 'jetton', 'nft'],
},
{
name: 'ActionDraft',
},
{
name: 'Intents',
types: ['txDraft', 'signMsgDraft', 'actionDraft', 'signData'],
},
] as unknown as Feature[];
}
28 changes: 23 additions & 5 deletions packages/walletkit-android-bridge/src/api/eventListeners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,36 @@ import type {
RequestErrorEvent,
SendTransactionRequestEvent,
SignDataRequestEvent,
IntentRequestEvent,
BatchedIntentEvent,
} from '@ton/walletkit';

type ConnectEventListener = ((event: ConnectionRequestEvent) => void) | null;
type TransactionEventListener = ((event: SendTransactionRequestEvent) => void) | null;
type SignDataEventListener = ((event: SignDataRequestEvent) => void) | null;
type DisconnectEventListener = ((event: DisconnectionEvent) => void) | null;
type ErrorEventListener = ((event: RequestErrorEvent) => void) | null;
/**
* Shared event listener references used to manage WalletKit callbacks.
*/
export type ConnectEventListener = ((event: ConnectionRequestEvent) => void) | null;
export type TransactionEventListener = ((event: SendTransactionRequestEvent) => void) | null;
export type SignDataEventListener = ((event: SignDataRequestEvent) => void) | null;
export type DisconnectEventListener = ((event: DisconnectionEvent) => void) | null;
export type ErrorEventListener = ((event: RequestErrorEvent) => void) | null;
export type IntentEventListener = ((event: IntentRequestEvent | BatchedIntentEvent) => void) | null;

/**
* Union type for all bridge event listeners.
*/
export type BridgeEventListener =
| ConnectEventListener
| TransactionEventListener
| SignDataEventListener
| DisconnectEventListener
| ErrorEventListener
| IntentEventListener;

export const eventListeners = {
onConnectListener: null as ConnectEventListener,
onTransactionListener: null as TransactionEventListener,
onSignDataListener: null as SignDataEventListener,
onDisconnectListener: null as DisconnectEventListener,
onErrorListener: null as ErrorEventListener,
onIntentListener: null as IntentEventListener,
};
11 changes: 11 additions & 0 deletions packages/walletkit-android-bridge/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import * as tonconnect from './tonconnect';
import * as nft from './nft';
import * as jettons from './jettons';
import * as browser from './browser';
import * as intents from './intents';
import { eventListeners } from './eventListeners';

export { eventListeners };
Expand Down Expand Up @@ -89,4 +90,14 @@ export const api: WalletKitBridgeApi = {
emitBrowserPageFinished: browser.emitBrowserPageFinished,
emitBrowserError: browser.emitBrowserError,
emitBrowserBridgeRequest: browser.emitBrowserBridgeRequest,

// Intents
isIntentUrl: intents.isIntentUrl,
handleIntentUrl: intents.handleIntentUrl,
approveTransactionDraft: intents.approveTransactionDraft,
approveSignDataIntent: intents.approveSignDataIntent,
approveActionDraft: intents.approveActionDraft,
approveBatchedIntent: intents.approveBatchedIntent,
rejectIntent: intents.rejectIntent,
intentItemsToTransactionRequest: intents.intentItemsToTransactionRequest,
} as unknown as WalletKitBridgeApi;
18 changes: 18 additions & 0 deletions packages/walletkit-android-bridge/src/api/initialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import type {
RequestErrorEvent,
SendTransactionRequestEvent,
SignDataRequestEvent,
IntentRequestEvent,
BatchedIntentEvent,
} from '@ton/walletkit';

import type { WalletKitBridgeInitConfig, SetEventsListenersArgs, WalletKitBridgeEventCallback } from '../types';
Expand Down Expand Up @@ -105,6 +107,17 @@ export async function setEventsListeners(args?: SetEventsListenersArgs): Promise

kit.onRequestError(eventListeners.onErrorListener);

// Register intent listener
if (eventListeners.onIntentListener) {
kit.removeIntentRequestCallback(eventListeners.onIntentListener);
}

eventListeners.onIntentListener = (event: IntentRequestEvent | BatchedIntentEvent) => {
callback('intentRequest', event);
};

kit.onIntentRequest(eventListeners.onIntentListener);

return { ok: true };
}

Expand Down Expand Up @@ -139,5 +152,10 @@ export async function removeEventListeners(): Promise<{ ok: true }> {
eventListeners.onErrorListener = null;
}

if (eventListeners.onIntentListener) {
kit.removeIntentRequestCallback(eventListeners.onIntentListener);
eventListeners.onIntentListener = null;
}

return { ok: true };
}
45 changes: 45 additions & 0 deletions packages/walletkit-android-bridge/src/api/intents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* 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.
*
*/

/**
* intents.ts – Bridge API for intent operations
*/

import { kit } from '../utils/bridge';

export async function isIntentUrl(args: unknown[]) {
return kit('isIntentUrl', ...args);
}

export async function handleIntentUrl(args: unknown[]) {
return kit('handleIntentUrl', ...args);
}

export async function approveTransactionDraft(args: unknown[]) {
return kit('approveTransactionDraft', ...args);
}

export async function approveSignDataIntent(args: unknown[]) {
return kit('approveSignDataIntent', ...args);
}

export async function approveActionDraft(args: unknown[]) {
return kit('approveActionDraft', ...args);
}

export async function approveBatchedIntent(args: unknown[]) {
return kit('approveBatchedIntent', ...args);
}

export async function rejectIntent(args: unknown[]) {
return kit('rejectIntent', ...args);
}

export async function intentItemsToTransactionRequest(args: unknown[]) {
return kit('intentItemsToTransactionRequest', ...args);
}
72 changes: 72 additions & 0 deletions packages/walletkit-android-bridge/src/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ import type {
TransactionRequest,
Wallet,
WalletResponse,
IntentRequestEvent,
BatchedIntentEvent,
TransactionIntentRequestEvent,
SignDataIntentRequestEvent,
ActionIntentRequestEvent,
IntentTransactionResponse,
IntentSignDataResponse,
IntentErrorResponse,
IntentActionItem,
} from '@ton/walletkit';

/**
Expand Down Expand Up @@ -260,6 +269,56 @@ export interface HandleTonConnectUrlArgs {
url: string;
}

// === Intent Args ===

export interface HandleIntentUrlArgs {
url: string;
walletId: string;
}

export interface IsIntentUrlArgs {
url: string;
}

export interface ApproveTransactionDraftArgs {
event: TransactionIntentRequestEvent;
walletId: string;
}

export interface ApproveSignDataDraftArgs {
event: SignDataIntentRequestEvent;
walletId: string;
}

export interface ApproveActionDraftArgs {
event: ActionIntentRequestEvent;
walletId: string;
}

export interface ApproveBatchedIntentArgs {
batch: BatchedIntentEvent;
walletId: string;
}

export interface RejectIntentArgs {
event: IntentRequestEvent | BatchedIntentEvent;
reason?: string;
errorCode?: number;
}

export interface IntentItemsToTransactionRequestArgs {
items: IntentActionItem[];
walletId: string;
}

export interface WalletDescriptor {
address: string;
publicKey: string;
version: string;
index: number;
network: string;
}

export interface WalletKitBridgeApi {
init(config?: WalletKitBridgeInitConfig): PromiseOrValue<{ ok: true }>;
setEventsListeners(args?: SetEventsListenersArgs): PromiseOrValue<{ ok: true }>;
Expand Down Expand Up @@ -311,4 +370,17 @@ export interface WalletKitBridgeApi {
emitBrowserPageFinished(args: EmitBrowserPageArgs): PromiseOrValue<{ success: boolean }>;
emitBrowserError(args: EmitBrowserErrorArgs): PromiseOrValue<{ success: boolean }>;
emitBrowserBridgeRequest(args: EmitBrowserBridgeRequestArgs): PromiseOrValue<{ success: boolean }>;
// Intent API
isIntentUrl(args: IsIntentUrlArgs): PromiseOrValue<boolean>;
handleIntentUrl(args: HandleIntentUrlArgs): PromiseOrValue<void>;
approveTransactionDraft(args: ApproveTransactionDraftArgs): PromiseOrValue<IntentTransactionResponse>;
approveSignDataIntent(args: ApproveSignDataDraftArgs): PromiseOrValue<IntentSignDataResponse>;
approveActionDraft(
args: ApproveActionDraftArgs,
): PromiseOrValue<IntentTransactionResponse | IntentSignDataResponse>;
approveBatchedIntent(
args: ApproveBatchedIntentArgs,
): PromiseOrValue<IntentTransactionResponse | IntentSignDataResponse>;
rejectIntent(args: RejectIntentArgs): PromiseOrValue<IntentErrorResponse>;
intentItemsToTransactionRequest(args: IntentItemsToTransactionRequestArgs): PromiseOrValue<TransactionRequest>;
}
1 change: 1 addition & 0 deletions packages/walletkit-android-bridge/src/types/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type WalletKitBridgeEventType =
| 'signDataRequest'
| 'disconnect'
| 'requestError'
| 'intentRequest'
| 'browserPageStarted'
| 'browserPageFinished'
| 'browserError'
Expand Down
30 changes: 30 additions & 0 deletions packages/walletkit-android-bridge/src/types/walletkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,28 @@

import type {
ApiClient,
BatchedIntentEvent,
BridgeEventMessageInfo,
ConnectionApprovalResponse,
ConnectionRequestEvent,
DeviceInfo,
DisconnectionEvent,
InjectedToExtensionBridgeRequestPayload,
IntentActionItem,
IntentErrorResponse,
IntentRequestEvent,
IntentSignDataResponse,
IntentTransactionResponse,
ActionIntentRequestEvent,
Network,
RequestErrorEvent,
SendTransactionApprovalResponse,
SendTransactionRequestEvent,
SignDataApprovalResponse,
SignDataIntentRequestEvent,
SignDataRequestEvent,
TONConnectSession,
TransactionIntentRequestEvent,
TransactionRequest,
Wallet,
WalletAdapter,
Expand Down Expand Up @@ -114,4 +123,25 @@ export interface WalletKitInstance {
event: SignDataRequestEvent,
reason?: string | SendTransactionRpcResponseError['error'],
): Promise<void>;
// Intent API
isIntentUrl(url: string): boolean;
handleIntentUrl(url: string, walletId: string): Promise<void>;
onIntentRequest(cb: (event: IntentRequestEvent | BatchedIntentEvent) => void): void;
removeIntentRequestCallback(cb: (event: IntentRequestEvent | BatchedIntentEvent) => void): void;
approveTransactionDraft(event: TransactionIntentRequestEvent, walletId: string): Promise<IntentTransactionResponse>;
approveSignDataIntent(event: SignDataIntentRequestEvent, walletId: string): Promise<IntentSignDataResponse>;
approveActionDraft(
event: ActionIntentRequestEvent,
walletId: string,
): Promise<IntentTransactionResponse | IntentSignDataResponse>;
approveBatchedIntent(
batch: BatchedIntentEvent,
walletId: string,
): Promise<IntentTransactionResponse | IntentSignDataResponse>;
rejectIntent(
event: IntentRequestEvent | BatchedIntentEvent,
reason?: string,
errorCode?: number,
): Promise<IntentErrorResponse>;
intentItemsToTransactionRequest(items: IntentActionItem[], walletId: string): Promise<TransactionRequest>;
}
4 changes: 3 additions & 1 deletion packages/walletkit/src/api/interfaces/WalletAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ export interface WalletAdapter {
getSignedSendTransaction(
input: TransactionRequest,
options?: {
fakeSignature: boolean;
fakeSignature?: boolean;
/** Use internal message opcode (0x73696e74) instead of external (0x7369676e) for gasless relaying */
internal?: boolean;
},
): Promise<Base64String>;
getSignedSignData(
Expand Down
21 changes: 21 additions & 0 deletions packages/walletkit/src/api/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,26 @@ export type {
TransactionTraceMoneyFlowItem,
} from './transactions/TransactionTraceMoneyFlow';

// Intent models
export type { SendTonAction, SendJettonAction, SendNftAction, IntentActionItem } from './intents/IntentActionItem';
export type {
IntentOrigin,
IntentDeliveryMode,
IntentRequestBase,
TransactionIntentRequestEvent,
SignDataIntentRequestEvent,
ActionIntentRequestEvent,
ConnectIntentRequestEvent,
IntentRequestEvent,
} from './intents/IntentRequestEvent';
export type {
IntentTransactionResponse,
IntentSignDataResponse,
IntentErrorResponse,
IntentError,
IntentResponseResult,
} from './intents/IntentResponse';
export type { BatchedIntentEvent } from './intents/BatchedIntentEvent';

// RPC models
export type { GetMethodResult } from './rpc/GetMethodResult';
29 changes: 29 additions & 0 deletions packages/walletkit/src/api/models/intents/BatchedIntentEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* 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 { BridgeEvent } from '../bridge/BridgeEvent';
import type { IntentRequestEvent, IntentOrigin } from './IntentRequestEvent';

/**
* A batched intent event containing multiple intent items
* that should be processed as a group.
*
* Use cases:
* - send TON + connect (intent with connect request)
* - action intent that resolves to multiple steps
*/
export interface BatchedIntentEvent extends BridgeEvent {
/** Discriminant — always 'batched' */
type: 'batched';
/** How the batch reached the wallet */
origin: IntentOrigin;
/** Client public key for response routing */
clientId?: string;
/** The intent requests in this batch */
intents: IntentRequestEvent[];
}
Loading
Loading