Skip to content
Open
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
14 changes: 9 additions & 5 deletions packages/walletkit-ios-bridge/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<WalletAdapter> {
if (!initialized) throw new Error('WalletKit Bridge not initialized');

Expand All @@ -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<WalletAdapter> {
if (!initialized) throw new Error('WalletKit Bridge not initialized');

Expand All @@ -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,
});
},
Expand Down Expand Up @@ -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<void> {
Expand Down
7 changes: 4 additions & 3 deletions packages/walletkit-ios-bridge/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
Hex,
ManifestFetchResult,
Network,
SignatureDomain,
TonWalletKitOptions,
WalletSigner,
WalletAdapter,
Expand Down Expand Up @@ -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<WalletAdapter>;

createV5R1WalletAdapter(
signer: WalletSigner | SwiftWalletSigner,
parameters: { network: Network },
parameters: { network: Network; domain?: SignatureDomain; walletId?: number | bigint; workchain?: number },
): Promise<WalletAdapter>;

jsSigner(signer: WalletSigner | SwiftWalletSigner): WalletSigner;
Expand All @@ -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<void>;

Expand Down
26 changes: 26 additions & 0 deletions packages/walletkit/src/api/scripts/generate-json-schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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<TQuoteMetadata>`. 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();
Expand Down Expand Up @@ -1042,6 +1060,7 @@ class GenericInterfaceNodeParser {
description,
format,
genericTypeRef,
genericInstanceType,
});
}
}
Expand Down Expand Up @@ -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<TQuoteMetadata>). 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);
Expand Down Expand Up @@ -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);
Expand Down
43 changes: 43 additions & 0 deletions packages/walletkit/src/api/scripts/generation-fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<TMeta>`). 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<TMeta>`.
// Covers required + optional. The bare `label` keeps the non-generic path live.

export interface GenericInstanceContainer<TMeta> {
inner: GenericContainer<TMeta>;
optionalInner?: GenericContainer<TMeta>;
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<A, B>`) →
// `TONMultiGenericContainer<A, B>`. The `@format int32` sibling checks the
// integer-format path still fires alongside x-generic-instance-type.

export interface GenericInstanceMultiArg<A, B> {
pair: MultiGenericContainer<A, B>;
/** @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<TUsed>`), 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<TUsed, TUnused> {
used: GenericContainer<TUsed>;
spare: TUnused;
}
Loading