It is then added to the NativeMessages object like so:
export type NativeMessages = {
eth_getBalance: EthGetBalanceMessage;
This exposes the message to the Messenger interface, which gives you eg type checking:
const balance = await Messenger.sendToNative(
'eth_getBalance',
sessionId,
{
unknownProperty: "foo" // Error: Property 'unknownProperty' is missing in type 'EthGetBalanceMessage'
}
);
The Messenger bus will handle serialisation, validation, error checking etc.
Swift
On the Swift side, messages are defined in Messages.swift and the Messages/*.swift files.
Messages.swift defines the NativeMessage and NativeMessageMethod types, and the NativeMessageParams protocol.
The Messages/*.swift files define the individual message params structs, which provide typing around each message's params:
struct helloFrenMessageParams: NativeMessageParams {
let foo: String
let bar: Int
let wagmi: Bool?
func execute(with userSettings: UserSettings) async throws -> Any {
if let wagmi = self.wagmi {
return wagmi ? "wagmi" : "ngmi"
}
return "ngmi"
}
}
The message param structs also implement the execute method, which is called by the SafariWebExtensionHandler#handle method. execute is passed the user settings, and returns a promise that resolves to the result of the message.
This allows the message params struct to pass on control to other parts of the Swift extension or core library in a type-safe way:
This PR introduces a fixed format for messaging between Swift and TypeScript.
Messaging between Swift and Typescript is governed by a fixed and typed interface. The basic object sent over the wire is of the form:
Typings need to be defined on both sides of the interface.
TypeScript
On the TypeScript side, messages are defined in
src/messaging/index.ts
and thesrc/messaging/messages/*.ts
files.src/messaging/index.ts
stores some utility types, and theNativeMessages
type, which maps method names (its keys) to a message object.The
src/messaging/messages/*.ts
files store the individual message objects, which specify the shape of the message, most importantly its parameters:It is then added to the
NativeMessages
object like so:This exposes the message to the Messenger interface, which gives you eg type checking:
The Messenger bus will handle serialisation, validation, error checking etc.
Swift
On the Swift side, messages are defined in
Messages.swift
and theMessages/*.swift
files.Messages.swift
defines theNativeMessage
andNativeMessageMethod
types, and theNativeMessageParams
protocol.The
Messages/*.swift
files define the individual message params structs, which provide typing around each message's params:The message param structs also implement the
execute
method, which is called by theSafariWebExtensionHandler#handle
method.execute
is passed the user settings, and returns a promise that resolves to the result of the message.This allows the message params struct to pass on control to other parts of the Swift extension or core library in a type-safe way:
Whatever is resolved from the
execute
method is returned as a JSON response, wrapped in amessage
key.NativeMessageParams
adheres to theDecodable
protocol, which allows you to customise the decoding behaviour:Explicitly not included in this PR, but up next, is:
ProviderAPI