diff --git a/packages/walletkit-ios-bridge/src/main.ts b/packages/walletkit-ios-bridge/src/main.ts index 6d5c20f6e..b8735ec8e 100644 --- a/packages/walletkit-ios-bridge/src/main.ts +++ b/packages/walletkit-ios-bridge/src/main.ts @@ -280,7 +280,7 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, sessionMa async createV4R2WalletAdapter( signer: WalletSigner | SwiftWalletSigner, - parameters: { network: Network; domain?: SignatureDomain }, + parameters: { network: Network; domain?: SignatureDomain; walletId?: number | bigint; workchain?: number }, ): Promise { if (!initialized) throw new Error('WalletKit Bridge not initialized'); @@ -296,13 +296,15 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, sessionMa return await WalletV4R2Adapter.create(this.jsSigner(signer), { client: walletKit.getApiClient(network), network: network, + walletId: parameters.walletId, + workchain: parameters.workchain, domain: parameters.domain, }); }, async createV5R1WalletAdapter( signer: WalletSigner | SwiftWalletSigner, - parameters: { network: Network; domain?: SignatureDomain }, + parameters: { network: Network; domain?: SignatureDomain; walletId?: number | bigint; workchain?: number }, ): Promise { if (!initialized) throw new Error('WalletKit Bridge not initialized'); @@ -318,6 +320,8 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, sessionMa return await WalletV5R1Adapter.create(this.jsSigner(signer), { client: walletKit.getApiClient(network), network: network, + walletId: parameters.walletId, + workchain: parameters.workchain, domain: parameters.domain, }); }, @@ -368,11 +372,11 @@ window.initWalletKit = async (configuration, storage, bridgeTransport, sessionMa return walletAdapter; }, - getWallet(address: string): Wallet | undefined { + getWallet(walletId: string): Wallet | undefined { if (!initialized) throw new Error('WalletKit Bridge not initialized'); - console.log('🔍 Bridge: Getting wallet for address:', address); - return walletKit.getWallet(address); + console.log('🔍 Bridge: Getting wallet for walletId:', walletId); + return walletKit.getWallet(walletId); }, async removeWallet(address: string): Promise { diff --git a/packages/walletkit-ios-bridge/src/types.ts b/packages/walletkit-ios-bridge/src/types.ts index 768c97eea..ec9e72d36 100644 --- a/packages/walletkit-ios-bridge/src/types.ts +++ b/packages/walletkit-ios-bridge/src/types.ts @@ -11,6 +11,7 @@ import type { Hex, ManifestFetchResult, Network, + SignatureDomain, TonWalletKitOptions, WalletSigner, WalletAdapter, @@ -95,12 +96,12 @@ export interface SwiftWalletKit { createV4R2WalletAdapter( signer: WalletSigner | SwiftWalletSigner, - parameters: { network: Network }, + parameters: { network: Network; domain?: SignatureDomain; walletId?: number | bigint; workchain?: number }, ): Promise; createV5R1WalletAdapter( signer: WalletSigner | SwiftWalletSigner, - parameters: { network: Network }, + parameters: { network: Network; domain?: SignatureDomain; walletId?: number | bigint; workchain?: number }, ): Promise; jsSigner(signer: WalletSigner | SwiftWalletSigner): WalletSigner; @@ -114,7 +115,7 @@ export interface SwiftWalletKit { jsWalletAdapter(walletAdapter: WalletAdapter): WalletAdapter; - getWallet(address: string): Wallet | undefined; + getWallet(walletId: string): Wallet | undefined; removeWallet(address: string): Promise; diff --git a/packages/walletkit/src/api/scripts/generate-json-schema.js b/packages/walletkit/src/api/scripts/generate-json-schema.js index a39d14cf1..2d262bfb4 100644 --- a/packages/walletkit/src/api/scripts/generate-json-schema.js +++ b/packages/walletkit/src/api/scripts/generate-json-schema.js @@ -989,6 +989,7 @@ class GenericInterfaceNodeParser { // Check if the property type references a generic type parameter let propType; let genericTypeRef = null; + let genericInstanceType = null; if (member.type) { const typeText = member.type.getText(); @@ -999,6 +1000,23 @@ class GenericInterfaceNodeParser { } else { // Parse the type normally propType = this.childNodeParser.createType(member.type, context); + + // Detect a generic instantiation parameterized by the parent's own type + // params, e.g. `CryptoOnrampQuote`. JSON Schema can't carry + // the type argument (it collapses to a $ref to the base), so capture the + // unprefixed Swift type text and let the template re-attach it. Restricted + // to the case where every argument is one of this interface's type params, + // so none of them need the model-name prefix. + if ( + ts.isTypeReferenceNode(member.type) && + member.type.typeArguments && + member.type.typeArguments.length > 0 && + member.type.typeArguments.every((arg) => typeParamNames.has(arg.getText())) + ) { + const baseName = member.type.typeName.getText(); + const argList = member.type.typeArguments.map((arg) => arg.getText()).join(', '); + genericInstanceType = `${baseName}<${argList}>`; + } } } else { propType = new tsj.AnyType(); @@ -1042,6 +1060,7 @@ class GenericInterfaceNodeParser { description, format, genericTypeRef, + genericInstanceType, }); } } @@ -1194,6 +1213,11 @@ class GenericInterfaceTypeFormatter { if (prop.genericTypeRef) { // Property uses a generic type parameter propDef['x-generic-type-ref'] = prop.genericTypeRef; + } else if (prop.genericInstanceType) { + // Property is a generic instantiation parameterized by the parent's type params + // (e.g. CryptoOnrampQuote). Emit it as a vendor extension instead + // of a $ref so the type argument survives to the Swift template. + propDef['x-generic-instance-type'] = prop.genericInstanceType; } else { // Get the normal type definition const typeDef = this.childTypeFormatter.getDefinition(prop.type); @@ -1269,6 +1293,8 @@ class GenericPropertiesObjectTypeFormatter { if (prop.genericTypeRef) { propDef['x-generic-type-ref'] = prop.genericTypeRef; + } else if (prop.genericInstanceType) { + propDef['x-generic-instance-type'] = prop.genericInstanceType; } else { const typeDef = this.childTypeFormatter.getDefinition(prop.type); Object.assign(propDef, typeDef); diff --git a/packages/walletkit/src/api/scripts/generation-fixtures.ts b/packages/walletkit/src/api/scripts/generation-fixtures.ts index 70b0ee8fd..6950b8191 100644 --- a/packages/walletkit/src/api/scripts/generation-fixtures.ts +++ b/packages/walletkit/src/api/scripts/generation-fixtures.ts @@ -382,3 +382,46 @@ export interface DiscriminatedUnionWithFormatB { /** @format uint16 */ code: number; } + +// ---------------------------------------------------------------------------- +// Case 25: Generic instantiation property (single type argument) +// ---------------------------------------------------------------------------- +// Exercises the x-generic-instance-type path in GenericInterfaceNodeParser: +// a property whose type is another generic type parameterized by THIS +// interface's own type param (`GenericContainer`). JSON Schema can't +// carry the type argument, so the parser records the raw Swift type text and +// the template re-attaches it (prefixed) → `TONGenericContainer`. +// Covers required + optional. The bare `label` keeps the non-generic path live. + +export interface GenericInstanceContainer { + inner: GenericContainer; + optionalInner?: GenericContainer; + label: string; +} + +// ---------------------------------------------------------------------------- +// Case 26: Generic instantiation with multiple type arguments +// ---------------------------------------------------------------------------- +// Like Case 25 but the instantiated type takes two arguments, both of which +// are the parent's type params (`MultiGenericContainer`) → +// `TONMultiGenericContainer`. The `@format int32` sibling checks the +// integer-format path still fires alongside x-generic-instance-type. + +export interface GenericInstanceMultiArg { + pair: MultiGenericContainer; + /** @format int32 */ + count: number; +} + +// ---------------------------------------------------------------------------- +// Case 27: Generic instantiation using a subset of the parent's type params +// ---------------------------------------------------------------------------- +// The parent declares two type params but the instantiation uses only one +// (`GenericContainer`), while the other (`TUnused`) is consumed by a +// bare generic-type-ref property. Verifies that x-generic-instance-type emits +// exactly the used argument and coexists with x-generic-type-ref. + +export interface GenericInstanceSubsetArg { + used: GenericContainer; + spare: TUnused; +}