@farcaster/miniapp-host 0.0.0-canary-20250630212339
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +15 -0
- package/dist/comlink/comlink.d.ts +150 -0
- package/dist/comlink/comlink.js +380 -0
- package/dist/comlink/index.d.ts +1 -0
- package/dist/comlink/index.js +1 -0
- package/dist/comlink/node-adapter.d.ts +13 -0
- package/dist/comlink/node-adapter.js +32 -0
- package/dist/comlink/protocol.d.ts +75 -0
- package/dist/comlink/protocol.js +21 -0
- package/dist/helpers/endpoint.d.ts +20 -0
- package/dist/helpers/endpoint.js +38 -0
- package/dist/helpers/ethereumProvider.d.ts +41 -0
- package/dist/helpers/ethereumProvider.js +89 -0
- package/dist/helpers/sdk.d.ts +2 -0
- package/dist/helpers/sdk.js +52 -0
- package/dist/iframe.d.ts +21 -0
- package/dist/iframe.js +50 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js +1 -0
- package/package.json +34 -0
- package/src/comlink/comlink.ts +654 -0
- package/src/comlink/index.ts +1 -0
- package/src/comlink/node-adapter.ts +49 -0
- package/src/comlink/protocol.ts +111 -0
- package/src/helpers/endpoint.ts +75 -0
- package/src/helpers/ethereumProvider.ts +125 -0
- package/src/helpers/sdk.ts +59 -0
- package/src/iframe.ts +80 -0
- package/src/index.ts +4 -0
- package/src/types.ts +10 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2019 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
export var WireValueType;
|
|
7
|
+
(function (WireValueType) {
|
|
8
|
+
WireValueType["RAW"] = "RAW";
|
|
9
|
+
WireValueType["PROXY"] = "PROXY";
|
|
10
|
+
WireValueType["THROW"] = "THROW";
|
|
11
|
+
WireValueType["HANDLER"] = "HANDLER";
|
|
12
|
+
})(WireValueType || (WireValueType = {}));
|
|
13
|
+
export var MessageType;
|
|
14
|
+
(function (MessageType) {
|
|
15
|
+
MessageType["GET"] = "GET";
|
|
16
|
+
MessageType["SET"] = "SET";
|
|
17
|
+
MessageType["APPLY"] = "APPLY";
|
|
18
|
+
MessageType["CONSTRUCT"] = "CONSTRUCT";
|
|
19
|
+
MessageType["ENDPOINT"] = "ENDPOINT";
|
|
20
|
+
MessageType["RELEASE"] = "RELEASE";
|
|
21
|
+
})(MessageType || (MessageType = {}));
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MiniAppHost } from '@farcaster/miniapp-core';
|
|
2
|
+
import type * as Provider from 'ox/Provider';
|
|
3
|
+
import type { HostEndpoint } from '../types.ts';
|
|
4
|
+
/**
|
|
5
|
+
* @returns function to cleanup provider listeners
|
|
6
|
+
*/
|
|
7
|
+
export declare function exposeToEndpoint({ endpoint, sdk, miniAppOrigin, ethProvider, debug, }: {
|
|
8
|
+
endpoint: HostEndpoint;
|
|
9
|
+
sdk: Omit<MiniAppHost, 'ethProviderRequestV2'>;
|
|
10
|
+
miniAppOrigin: string;
|
|
11
|
+
ethProvider?: Provider.Provider;
|
|
12
|
+
debug?: boolean;
|
|
13
|
+
}): () => void;
|
|
14
|
+
export declare function useExposeToEndpoint({ endpoint, sdk, miniAppOrigin, ethProvider, debug, }: {
|
|
15
|
+
endpoint: HostEndpoint | undefined;
|
|
16
|
+
sdk: Omit<MiniAppHost, 'ethProviderRequestV2'>;
|
|
17
|
+
miniAppOrigin: string;
|
|
18
|
+
ethProvider?: Provider.Provider;
|
|
19
|
+
debug?: boolean;
|
|
20
|
+
}): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import * as Comlink from "../comlink/index.js";
|
|
3
|
+
import { forwardEthereumProviderEvents, wrapEthereumProviderRequest, } from "./ethereumProvider.js";
|
|
4
|
+
import { wrapHandlers } from "./sdk.js";
|
|
5
|
+
/**
|
|
6
|
+
* @returns function to cleanup provider listeners
|
|
7
|
+
*/
|
|
8
|
+
export function exposeToEndpoint({ endpoint, sdk, miniAppOrigin, ethProvider, debug = false, }) {
|
|
9
|
+
const extendedSdk = wrapHandlers(sdk);
|
|
10
|
+
let cleanup;
|
|
11
|
+
if (ethProvider) {
|
|
12
|
+
extendedSdk.ethProviderRequestV2 = wrapEthereumProviderRequest({
|
|
13
|
+
provider: ethProvider,
|
|
14
|
+
debug,
|
|
15
|
+
});
|
|
16
|
+
cleanup = forwardEthereumProviderEvents({ provider: ethProvider, endpoint });
|
|
17
|
+
}
|
|
18
|
+
const unexpose = Comlink.expose(extendedSdk, endpoint, [miniAppOrigin]);
|
|
19
|
+
return () => {
|
|
20
|
+
cleanup?.();
|
|
21
|
+
unexpose();
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function useExposeToEndpoint({ endpoint, sdk, miniAppOrigin, ethProvider, debug = false, }) {
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (!endpoint) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const cleanup = exposeToEndpoint({
|
|
30
|
+
endpoint,
|
|
31
|
+
sdk,
|
|
32
|
+
miniAppOrigin,
|
|
33
|
+
ethProvider,
|
|
34
|
+
debug,
|
|
35
|
+
});
|
|
36
|
+
return cleanup;
|
|
37
|
+
}, [endpoint, sdk, ethProvider, miniAppOrigin, debug]);
|
|
38
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as Provider from 'ox/Provider';
|
|
2
|
+
import type * as RpcRequest from 'ox/RpcRequest';
|
|
3
|
+
import * as RpcResponse from 'ox/RpcResponse';
|
|
4
|
+
import type { HostEndpoint } from '../types.ts';
|
|
5
|
+
export declare function forwardEthereumProviderEvents({ provider, endpoint, }: {
|
|
6
|
+
provider: Provider.Provider;
|
|
7
|
+
endpoint: HostEndpoint;
|
|
8
|
+
}): () => void;
|
|
9
|
+
/**
|
|
10
|
+
* Wraps a provider's request function with a result format that can transfer
|
|
11
|
+
* errors across scripting boundaries.
|
|
12
|
+
*/
|
|
13
|
+
export declare const wrapEthereumProviderRequest: ({ provider, debug, }: {
|
|
14
|
+
provider: Provider.Provider;
|
|
15
|
+
debug?: boolean;
|
|
16
|
+
}) => (request: RpcRequest.RpcRequest) => Promise<{
|
|
17
|
+
id: number;
|
|
18
|
+
jsonrpc: "2.0";
|
|
19
|
+
error: RpcResponse.ErrorObject;
|
|
20
|
+
result?: undefined;
|
|
21
|
+
} | {
|
|
22
|
+
id: number;
|
|
23
|
+
jsonrpc: "2.0";
|
|
24
|
+
result: unknown;
|
|
25
|
+
error?: undefined;
|
|
26
|
+
} | {
|
|
27
|
+
readonly error: {
|
|
28
|
+
readonly message: string;
|
|
29
|
+
readonly code: number;
|
|
30
|
+
readonly details: string | undefined;
|
|
31
|
+
};
|
|
32
|
+
readonly id: number;
|
|
33
|
+
readonly jsonrpc: "2.0";
|
|
34
|
+
} | {
|
|
35
|
+
readonly error: {
|
|
36
|
+
readonly message: string;
|
|
37
|
+
readonly code: 1000;
|
|
38
|
+
};
|
|
39
|
+
readonly id: number;
|
|
40
|
+
readonly jsonrpc: "2.0";
|
|
41
|
+
}>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as Provider from 'ox/Provider';
|
|
2
|
+
import * as RpcResponse from 'ox/RpcResponse';
|
|
3
|
+
export function forwardEthereumProviderEvents({ provider, endpoint, }) {
|
|
4
|
+
const accountsChanged = (accounts) => {
|
|
5
|
+
endpoint.emitEthProvider('accountsChanged', [accounts]);
|
|
6
|
+
};
|
|
7
|
+
const chainChanged = (chainId) => {
|
|
8
|
+
endpoint.emitEthProvider('chainChanged', [chainId]);
|
|
9
|
+
};
|
|
10
|
+
const connect = (connectInfo) => {
|
|
11
|
+
endpoint.emitEthProvider('connect', [connectInfo]);
|
|
12
|
+
};
|
|
13
|
+
const disconnect = (providerRpcError) => {
|
|
14
|
+
endpoint.emitEthProvider('disconnect', [providerRpcError]);
|
|
15
|
+
};
|
|
16
|
+
const message = (message) => {
|
|
17
|
+
endpoint.emitEthProvider('message', [message]);
|
|
18
|
+
};
|
|
19
|
+
provider.on('accountsChanged', accountsChanged);
|
|
20
|
+
provider.on('chainChanged', chainChanged);
|
|
21
|
+
provider.on('connect', connect);
|
|
22
|
+
provider.on('disconnect', disconnect);
|
|
23
|
+
provider.on('message', message);
|
|
24
|
+
return () => {
|
|
25
|
+
provider.removeListener('accountsChanged', accountsChanged);
|
|
26
|
+
provider.removeListener('chainChanged', chainChanged);
|
|
27
|
+
provider.removeListener('connect', connect);
|
|
28
|
+
provider.removeListener('disconnect', disconnect);
|
|
29
|
+
provider.removeListener('message', message);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// export type FrameTransport<
|
|
33
|
+
// raw extends boolean = false,
|
|
34
|
+
// schema extends RpcSchema.Generic = RpcSchema.Default,
|
|
35
|
+
// > = RP RpcTransport<raw, {}, schema>
|
|
36
|
+
/**
|
|
37
|
+
* Wraps a provider's request function with a result format that can transfer
|
|
38
|
+
* errors across scripting boundaries.
|
|
39
|
+
*/
|
|
40
|
+
export const wrapEthereumProviderRequest = ({ provider, debug = false, }) => async (request) => {
|
|
41
|
+
try {
|
|
42
|
+
if (debug) {
|
|
43
|
+
console.debug('[miniapp-host] eth provider req: ', request);
|
|
44
|
+
}
|
|
45
|
+
const result = await provider.request(request);
|
|
46
|
+
const response = RpcResponse.from({ result }, { request });
|
|
47
|
+
if (debug) {
|
|
48
|
+
console.debug('[miniapp-host] eth provider res: ', response);
|
|
49
|
+
}
|
|
50
|
+
return response;
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
if (debug) {
|
|
54
|
+
console.error('provider request error', e);
|
|
55
|
+
}
|
|
56
|
+
if (e instanceof Provider.ProviderRpcError) {
|
|
57
|
+
return RpcResponse.from({
|
|
58
|
+
error: {
|
|
59
|
+
message: e.message,
|
|
60
|
+
code: e.code,
|
|
61
|
+
details: e.details,
|
|
62
|
+
},
|
|
63
|
+
}, { request });
|
|
64
|
+
}
|
|
65
|
+
if (e !== null &&
|
|
66
|
+
typeof e === 'object' &&
|
|
67
|
+
'message' in e &&
|
|
68
|
+
typeof e.message === 'string' &&
|
|
69
|
+
'code' in e &&
|
|
70
|
+
typeof e.code === 'number') {
|
|
71
|
+
return RpcResponse.from({
|
|
72
|
+
error: {
|
|
73
|
+
message: e.message,
|
|
74
|
+
code: e.code,
|
|
75
|
+
details: 'details' in e && typeof e.details === 'string'
|
|
76
|
+
? e.details
|
|
77
|
+
: undefined,
|
|
78
|
+
},
|
|
79
|
+
}, { request });
|
|
80
|
+
}
|
|
81
|
+
const errorMessage = e instanceof Error ? e.message : 'Unknown';
|
|
82
|
+
return RpcResponse.from({
|
|
83
|
+
error: {
|
|
84
|
+
message: errorMessage,
|
|
85
|
+
code: 1000,
|
|
86
|
+
},
|
|
87
|
+
}, { request });
|
|
88
|
+
}
|
|
89
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { AddMiniApp, SignIn, wrapSolanaProviderRequest, } from '@farcaster/miniapp-core';
|
|
2
|
+
export function wrapHandlers(host) {
|
|
3
|
+
return {
|
|
4
|
+
...host,
|
|
5
|
+
addMiniApp: async () => {
|
|
6
|
+
try {
|
|
7
|
+
const result = await host.addMiniApp();
|
|
8
|
+
return { result };
|
|
9
|
+
}
|
|
10
|
+
catch (e) {
|
|
11
|
+
if (e instanceof AddMiniApp.RejectedByUser) {
|
|
12
|
+
return {
|
|
13
|
+
error: {
|
|
14
|
+
type: 'rejected_by_user',
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (e instanceof AddMiniApp.InvalidDomainManifest) {
|
|
19
|
+
return {
|
|
20
|
+
error: {
|
|
21
|
+
type: 'invalid_domain_manifest',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
throw e;
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
signIn: async (options) => {
|
|
29
|
+
try {
|
|
30
|
+
const result = await host.signIn(options);
|
|
31
|
+
return { result };
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
if (e instanceof SignIn.RejectedByUser) {
|
|
35
|
+
return {
|
|
36
|
+
error: {
|
|
37
|
+
type: 'rejected_by_user',
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
throw e;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
solanaProviderRequest: host.solanaProviderRequest
|
|
45
|
+
? wrapSolanaProviderRequest(host.solanaProviderRequest)
|
|
46
|
+
: undefined,
|
|
47
|
+
// Pass through haptics methods directly
|
|
48
|
+
impactOccurred: host.impactOccurred,
|
|
49
|
+
notificationOccurred: host.notificationOccurred,
|
|
50
|
+
selectionChanged: host.selectionChanged,
|
|
51
|
+
};
|
|
52
|
+
}
|
package/dist/iframe.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { MiniAppHost } from '@farcaster/miniapp-core';
|
|
2
|
+
import type { Provider } from 'ox/Provider';
|
|
3
|
+
import type { HostEndpoint } from './types.ts';
|
|
4
|
+
/**
|
|
5
|
+
* An endpoint of communicating with an iFrame
|
|
6
|
+
*/
|
|
7
|
+
export declare function createIframeEndpoint({ iframe, targetOrigin, debug, }: {
|
|
8
|
+
iframe: HTMLIFrameElement;
|
|
9
|
+
targetOrigin: string;
|
|
10
|
+
debug?: boolean;
|
|
11
|
+
}): HostEndpoint;
|
|
12
|
+
export declare function exposeToIframe({ iframe, sdk, ethProvider, miniAppOrigin, debug, }: {
|
|
13
|
+
iframe: HTMLIFrameElement;
|
|
14
|
+
sdk: Omit<MiniAppHost, 'ethProviderRequestV2'>;
|
|
15
|
+
miniAppOrigin: string;
|
|
16
|
+
ethProvider?: Provider;
|
|
17
|
+
debug?: boolean;
|
|
18
|
+
}): {
|
|
19
|
+
endpoint: HostEndpoint;
|
|
20
|
+
cleanup: () => void;
|
|
21
|
+
};
|
package/dist/iframe.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as Comlink from "./comlink/index.js";
|
|
2
|
+
import { exposeToEndpoint } from "./helpers/endpoint.js";
|
|
3
|
+
/**
|
|
4
|
+
* An endpoint of communicating with an iFrame
|
|
5
|
+
*/
|
|
6
|
+
export function createIframeEndpoint({ iframe, targetOrigin, debug = true, }) {
|
|
7
|
+
return {
|
|
8
|
+
// when is contentWindow null
|
|
9
|
+
...Comlink.windowEndpoint(iframe.contentWindow),
|
|
10
|
+
emit: (event) => {
|
|
11
|
+
if (debug) {
|
|
12
|
+
console.debug('frameEvent', event);
|
|
13
|
+
}
|
|
14
|
+
const wireEvent = {
|
|
15
|
+
type: 'frameEvent',
|
|
16
|
+
event,
|
|
17
|
+
};
|
|
18
|
+
iframe.contentWindow?.postMessage(wireEvent, targetOrigin);
|
|
19
|
+
},
|
|
20
|
+
emitEthProvider: (event, params) => {
|
|
21
|
+
if (debug) {
|
|
22
|
+
console.debug('fc:emitEthProvider', event, params);
|
|
23
|
+
}
|
|
24
|
+
const wireEvent = {
|
|
25
|
+
type: 'frameEthProviderEvent',
|
|
26
|
+
event,
|
|
27
|
+
params,
|
|
28
|
+
};
|
|
29
|
+
iframe.contentWindow?.postMessage(wireEvent, targetOrigin);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function exposeToIframe({ iframe, sdk, ethProvider, miniAppOrigin, debug = false, }) {
|
|
34
|
+
const endpoint = createIframeEndpoint({
|
|
35
|
+
iframe,
|
|
36
|
+
targetOrigin: miniAppOrigin,
|
|
37
|
+
debug,
|
|
38
|
+
});
|
|
39
|
+
const cleanup = exposeToEndpoint({
|
|
40
|
+
endpoint,
|
|
41
|
+
sdk,
|
|
42
|
+
ethProvider,
|
|
43
|
+
miniAppOrigin,
|
|
44
|
+
debug,
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
endpoint,
|
|
48
|
+
cleanup,
|
|
49
|
+
};
|
|
50
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED