diff --git a/packages/walletkit-ios-bridge/src/main.ts b/packages/walletkit-ios-bridge/src/main.ts index 1be7fa48..b55b27aa 100644 --- a/packages/walletkit-ios-bridge/src/main.ts +++ b/packages/walletkit-ios-bridge/src/main.ts @@ -9,18 +9,42 @@ /* eslint-disable no-console */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import type { WalletSigner, BridgeEventMessageInfo, InjectedToExtensionBridgeRequestPayload } from '@ton/walletkit'; +import type { + WalletSigner, + BridgeEventMessageInfo, + InjectedToExtensionBridgeRequestPayload, + NetworkAdapters, + Wallet, + TransactionRequest, + SignDataRequestEvent, + TransactionRequestEvent, + ConnectionRequestEvent, + Network, + StorageAdapter, +} from '@ton/walletkit'; import { MemoryStorageAdapter, Signer, WalletV4R2Adapter, WalletV5R1Adapter, TonWalletKit } from '@ton/walletkit'; import type { WalletAdapter } from '@ton/walletkit'; import { SwiftStorageAdapter } from './SwiftStorageAdapter'; import { SwiftWalletAdapter } from './SwiftWalletAdapter'; import { SwiftAPIClientAdapter } from './SwiftAPIClientAdapter'; +import type { + SwiftApiClient, + SwiftBridgeTransport, + SwiftWalletKit, + SwiftWalletKitConfiguration, + SwiftWalletSigner, +} from './types'; declare global { interface Window { - walletKit?: any; - initWalletKit: (configuration, storage, bridgeTransport: (response) => void, apiClients) => Promise; + walletKit?: SwiftWalletKit; + initWalletKit: ( + configuration: SwiftWalletKitConfiguration, + storage?: StorageAdapter, + bridgeTransport?: SwiftBridgeTransport, + apiClients?: SwiftApiClient[], + ) => Promise; } } @@ -31,11 +55,13 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient console.log('Storage', storage); console.log('API Clients', apiClients); - configuration.bridge.jsBridgeTransport = (sessionID, message) => { - bridgeTransport({ sessionID, messageID: message.messageId, message }); - }; + if (configuration.bridge && bridgeTransport) { + configuration.bridge.jsBridgeTransport = (sessionID: string, message: any) => { + bridgeTransport({ sessionID, messageID: message.messageId, message }); + }; + } - const networks = {}; + const networks: NetworkAdapters = {}; if (configuration.networkConfigurations) { for (const netConfig of configuration.networkConfigurations) { networks[netConfig.network.chainId] = { @@ -44,15 +70,17 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient } } - for (const apiClient of apiClients) { - const network = apiClient.getNetwork(); - const client = new SwiftAPIClientAdapter(apiClient); + if (apiClients) { + for (const apiClient of apiClients) { + const network = apiClient.getNetwork(); + const client = new SwiftAPIClientAdapter(apiClient); - console.log('API Client Network', network); + console.log('API Client Network', network); - networks[network.chainId] = { - apiClient: client, - }; + networks[network.chainId] = { + apiClient: client, + }; + } } const walletKit = new TonWalletKit({ @@ -92,14 +120,14 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient window.walletKit = { // Check if initialized isReady() { - return initialized && walletKit; + return initialized && !!walletKit; }, jettonsManager() { return walletKit.jettons; }, - setEventsListeners(callback) { + setEventsListeners(callback: (type: string, event: unknown) => Promise) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('🔔 Bridge: Adding event listeners'); @@ -136,7 +164,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient console.log('🗑️ All event listeners removed'); }, - async createSignerFromMnemonic(mnemonic) { + async createSignerFromMnemonic(mnemonic: string) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('➕ Bridge: Creating signer from mnemonic'); @@ -148,7 +176,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient return await Signer.fromMnemonic(mnemonic, { type: 'ton' }); }, - async createSignerFromPrivateKey(privateKey) { + async createSignerFromPrivateKey(privateKey: string) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('➕ Bridge: Creating signer from private key'); @@ -160,7 +188,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient return await Signer.fromPrivateKey(privateKey); }, - async createV4R2WalletAdapter(signer, parameters) { + async createV4R2WalletAdapter(signer: WalletSigner | SwiftWalletSigner, parameters: { network: Network }) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('➕ Bridge: Creating V4R2 wallet using mnemonic'); @@ -178,7 +206,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient }); }, - async createV5R1WalletAdapter(signer, parameters) { + async createV5R1WalletAdapter(signer: WalletSigner | SwiftWalletSigner, parameters: { network: Network }) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('➕ Bridge: Creating V5R1 wallet using mnemonic'); @@ -196,16 +224,19 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient }); }, - jsSigner(signer): WalletSigner { + jsSigner(signer: WalletSigner | SwiftWalletSigner): WalletSigner { if (isSwiftObject(signer)) { + const swiftSigner = signer as SwiftWalletSigner; + return { sign: async (bytes: Iterable) => { - return await signer.sign(bytes); + return await swiftSigner.sign(bytes); }, - publicKey: signer.publicKey(), + publicKey: swiftSigner.publicKey(), }; } - return signer; + + return signer as WalletSigner; }, async processInjectedBridgeRequest( @@ -218,7 +249,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient }, // Wallet management - async addWallet(walletAdapter) { + async addWallet(walletAdapter: WalletAdapter) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('➕ Bridge: Adding wallet:'); @@ -232,21 +263,21 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient return wallet; }, - jsWalletAdapter(walletAdapter): WalletAdapter { + jsWalletAdapter(walletAdapter: WalletAdapter): WalletAdapter { if (isSwiftObject(walletAdapter)) { return new SwiftWalletAdapter(walletAdapter, walletKit.getApiClient(walletAdapter.getNetwork())); } return walletAdapter; }, - getWallet(address) { + getWallet(address: string) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('🔍 Bridge: Getting wallet for address:', address); return walletKit.getWallet(address); }, - async removeWallet(address) { + async removeWallet(address: string) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('➖ Bridge: Removing wallet:', address); @@ -264,9 +295,8 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient console.log('🗑️ Bridge: Clearing all wallets'); try { - const result = await walletKit.clearWallets(); - console.log('✅ All wallets cleared:', result); - return result; + await walletKit.clearWallets(); + console.log('✅ All wallets cleared'); } catch (error) { console.error('❌ Failed to clear wallets:', error); throw error; @@ -295,7 +325,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient }, // Connection handling - async handleTonConnectUrl(url) { + async handleTonConnectUrl(url: string) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('🔗 Bridge: Handling TON Connect URL:', url); @@ -309,7 +339,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient } }, - async approveConnectRequest(request) { + async approveConnectRequest(request: ConnectionRequestEvent) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('✅ Bridge: Approving connect request:', request, request.walletAddress); @@ -323,7 +353,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient } }, - async rejectConnectRequest(request, reason) { + async rejectConnectRequest(request: ConnectionRequestEvent, reason?: string) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('❌ Bridge: Rejecting connect request:', request.id, reason || 'User rejected'); @@ -338,7 +368,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient }, // Transaction handling - async approveTransactionRequest(request) { + async approveTransactionRequest(request: TransactionRequestEvent) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('✅ Bridge: Approving transaction request:', request); @@ -352,7 +382,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient } }, - async rejectTransactionRequest(request, reason) { + async rejectTransactionRequest(request: TransactionRequestEvent, reason?: string) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('❌ Bridge: Rejecting transaction request:', request, reason); @@ -367,7 +397,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient }, // Sign data handling - async approveSignDataRequest(request) { + async approveSignDataRequest(request: SignDataRequestEvent) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('✅ Bridge: Approving sign data request:', request); @@ -381,7 +411,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient } }, - async rejectSignDataRequest(request, reason) { + async rejectSignDataRequest(request: SignDataRequestEvent, reason?: string) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('❌ Bridge: Rejecting sign data request:', request, reason); @@ -396,7 +426,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient }, // Session management - async disconnect(sessionId) { + async disconnect(sessionId: string) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('🔌 Bridge: Disconnecting session:', sessionId); @@ -411,7 +441,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient }, // Jettons - async getJettons(walletAddress) { + async getJettons(walletAddress: string) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('🪙 Bridge: Getting jettons for:', walletAddress); @@ -425,7 +455,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient } }, - async sendTransaction(wallet, transaction) { + async sendTransaction(wallet: Wallet, transaction: TransactionRequest) { if (!initialized) throw new Error('WalletKit Bridge not initialized'); console.log('🪙 Bridge: Sending transaction:', transaction); @@ -434,7 +464,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, apiClient }; }; -function parseSwiftConstructorPattern(str) { +function parseSwiftConstructorPattern(str: string) { const match = str.match(/^\[object ([A-Za-z_$][A-Za-z0-9_$]*)\.([A-Za-z_$][A-Za-z0-9_$]*)Constructor\]$/); if (match) { @@ -448,10 +478,11 @@ function parseSwiftConstructorPattern(str) { return null; } -function isSwiftObject(obj) { +function isSwiftObject(obj: any) { if (obj && obj.constructor) { const pattern = parseSwiftConstructorPattern(obj.constructor.toString()); return pattern !== null; } + return false; } diff --git a/packages/walletkit-ios-bridge/src/types.ts b/packages/walletkit-ios-bridge/src/types.ts new file mode 100644 index 00000000..3110b391 --- /dev/null +++ b/packages/walletkit-ios-bridge/src/types.ts @@ -0,0 +1,114 @@ +/** + * 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 { + ApiClient, + Hex, + Network, + TonWalletKitOptions, + WalletSigner, + WalletAdapter, + Wallet, + TransactionRequest, + SignDataRequestEvent, + TransactionRequestEvent, + ConnectionRequestEvent, + BridgeEventMessageInfo, + InjectedToExtensionBridgeRequestPayload, + JettonsAPI, + SessionInfo, +} from '@ton/walletkit'; + +export interface SwiftApiClient extends ApiClient { + getNetwork: () => Network; +} + +export interface SwiftWalletSigner { + sign: (data: Iterable) => Promise; + publicKey: () => Hex; +} + +type ReusedTonWalletKitOptions = Pick; + +export interface SwiftWalletKitConfiguration extends ReusedTonWalletKitOptions { + networkConfigurations?: { + network: Network; + apiClientConfiguration?: { + url?: string; + key: string; + }; + }[]; + eventsConfiguration?: TonWalletKitOptions['eventProcessor']; +} + +export type SwiftBridgeTransport = (data: { sessionID: string; messageID: string; message: unknown }) => void; + +export interface SwiftWalletKit { + isReady(): boolean; + + jettonsManager(): JettonsAPI; + + setEventsListeners(callback: (type: string, event: unknown) => Promise): void; + + removeEventListeners(): void; + + createSignerFromMnemonic(mnemonic: string): Promise; + + createSignerFromPrivateKey(privateKey: string): Promise; + + createV4R2WalletAdapter( + signer: WalletSigner | SwiftWalletSigner, + parameters: { network: Network }, + ): Promise; + + createV5R1WalletAdapter( + signer: WalletSigner | SwiftWalletSigner, + parameters: { network: Network }, + ): Promise; + + jsSigner(signer: WalletSigner | SwiftWalletSigner): WalletSigner; + + processInjectedBridgeRequest( + messageInfo: BridgeEventMessageInfo, + request: InjectedToExtensionBridgeRequestPayload, + ): Promise; + + addWallet(walletAdapter: WalletAdapter): Promise; + + jsWalletAdapter(walletAdapter: WalletAdapter): WalletAdapter; + + getWallet(address: string): Wallet | undefined; + + removeWallet(address: string): Promise; + + clearWallets(): Promise; + + getWallets(): Wallet[]; + + getSessions(): Promise; + + handleTonConnectUrl(url: string): Promise; + + approveConnectRequest(request: ConnectionRequestEvent): Promise; + + rejectConnectRequest(request: ConnectionRequestEvent, reason?: string): Promise; + + approveTransactionRequest(request: TransactionRequestEvent): Promise; + + rejectTransactionRequest(request: TransactionRequestEvent, reason?: string): Promise; + + approveSignDataRequest(request: SignDataRequestEvent): Promise; + + rejectSignDataRequest(request: SignDataRequestEvent, reason?: string): Promise; + + disconnect(sessionId: string): Promise; + + getJettons(walletAddress: string): Promise; + + sendTransaction(wallet: Wallet, transaction: TransactionRequest): Promise; +}