@farcaster/frame-sdk 0.0.64 → 0.1.0
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/dist/index.d.ts +5 -6
- package/dist/index.js +26 -6
- package/dist/index.min.js +40 -12
- package/dist/index.min.js.map +4 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -4
- package/src/index.ts +35 -6
- package/dist/back.d.ts +0 -15
- package/dist/back.js +0 -88
- package/dist/endpoint.d.ts +0 -2
- package/dist/endpoint.js +0 -32
- package/dist/ethereumProvider.d.ts +0 -3
- package/dist/ethereumProvider.js +0 -132
- package/dist/frameHost.d.ts +0 -2
- package/dist/frameHost.js +0 -3
- package/dist/quickAuth.d.ts +0 -42
- package/dist/quickAuth.js +0 -74
- package/dist/sdk.d.ts +0 -2
- package/dist/sdk.js +0 -182
- package/dist/sdkEmitter.d.ts +0 -15
- package/dist/sdkEmitter.js +0 -23
- package/dist/solanaProvider.d.ts +0 -3
- package/dist/solanaProvider.js +0 -19
- package/dist/types.d.ts +0 -74
- package/dist/types.js +0 -1
- package/src/back.ts +0 -143
- package/src/endpoint.ts +0 -34
- package/src/ethereumProvider.ts +0 -183
- package/src/frameHost.ts +0 -5
- package/src/navigation.d.ts +0 -191
- package/src/quickAuth.ts +0 -148
- package/src/sdk.ts +0 -191
- package/src/sdkEmitter.ts +0 -27
- package/src/solanaProvider.ts +0 -33
- package/src/types.ts +0 -107
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farcaster/frame-sdk",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "https://github.com/farcasterxyz/
|
|
7
|
+
"url": "https://github.com/farcasterxyz/miniapps.git",
|
|
8
8
|
"directory": "packages/frame-sdk"
|
|
9
9
|
},
|
|
10
10
|
"main": "dist/index.js",
|
|
@@ -16,14 +16,17 @@
|
|
|
16
16
|
"esbuild": "^0.25.0",
|
|
17
17
|
"mipd": "^0.0.7",
|
|
18
18
|
"typescript": "^5.8.3",
|
|
19
|
-
"@farcaster/tsconfig": "0.0
|
|
19
|
+
"@farcaster/tsconfig": "0.1.0"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@farcaster/quick-auth": "^0.0.6",
|
|
23
23
|
"comlink": "^4.4.2",
|
|
24
24
|
"eventemitter3": "^5.0.1",
|
|
25
25
|
"ox": "^0.4.4",
|
|
26
|
-
"@farcaster/
|
|
26
|
+
"@farcaster/miniapp-sdk": "0.1.0"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=22.11.0"
|
|
27
30
|
},
|
|
28
31
|
"scripts": {
|
|
29
32
|
"clean": "rm -rf dist",
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,40 @@
|
|
|
1
|
-
|
|
1
|
+
// Deprecation warning
|
|
2
|
+
if (typeof console !== 'undefined' && console.warn) {
|
|
3
|
+
console.warn(
|
|
4
|
+
'[DEPRECATION WARNING] @farcaster/frame-sdk is deprecated. Please migrate to @farcaster/miniapp-sdk. ' +
|
|
5
|
+
'See https://github.com/farcasterxyz/frames/blob/main/MIGRATION.md for migration guide.',
|
|
6
|
+
)
|
|
7
|
+
}
|
|
2
8
|
|
|
3
|
-
export
|
|
4
|
-
export * from '
|
|
5
|
-
export * from '@farcaster/frame-core'
|
|
9
|
+
// Re-export everything from miniapp-sdk
|
|
10
|
+
export * from '@farcaster/miniapp-sdk'
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
// Import for aliasing
|
|
13
|
+
import { miniAppHost, sdk as miniAppSdk } from '@farcaster/miniapp-sdk'
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
// Backward compatibility exports
|
|
16
|
+
export const sdk = miniAppSdk
|
|
10
17
|
|
|
18
|
+
// Create a proxy for frameHost that logs deprecation warning on first access
|
|
19
|
+
let frameHostWarningShown = false
|
|
20
|
+
export const frameHost = new Proxy(miniAppHost, {
|
|
21
|
+
get(target, prop, receiver) {
|
|
22
|
+
if (
|
|
23
|
+
!frameHostWarningShown &&
|
|
24
|
+
typeof console !== 'undefined' &&
|
|
25
|
+
console.warn
|
|
26
|
+
) {
|
|
27
|
+
console.warn(
|
|
28
|
+
'[DEPRECATION WARNING] frameHost is deprecated. Please use miniAppHost instead. ' +
|
|
29
|
+
'Import from @farcaster/miniapp-sdk and use miniAppHost.',
|
|
30
|
+
)
|
|
31
|
+
frameHostWarningShown = true
|
|
32
|
+
}
|
|
33
|
+
return Reflect.get(target, prop, receiver)
|
|
34
|
+
},
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
export type FrameSDK = typeof miniAppSdk
|
|
38
|
+
|
|
39
|
+
// Default export
|
|
11
40
|
export default sdk
|
package/dist/back.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { WireFrameHost } from '@farcaster/frame-core';
|
|
2
|
-
import type { Remote } from 'comlink';
|
|
3
|
-
import type { Emitter } from './types.ts';
|
|
4
|
-
export type Back = {
|
|
5
|
-
visible: boolean;
|
|
6
|
-
show: () => Promise<void>;
|
|
7
|
-
hide: () => Promise<void>;
|
|
8
|
-
onback: (() => unknown) | null;
|
|
9
|
-
enableWebNavigation: () => Promise<void>;
|
|
10
|
-
disableWebNavigation: () => Promise<void>;
|
|
11
|
-
};
|
|
12
|
-
export declare const createBack: (options: {
|
|
13
|
-
emitter: Emitter;
|
|
14
|
-
frameHost: Remote<WireFrameHost>;
|
|
15
|
-
}) => Back;
|
package/dist/back.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
export const createBack = ({ frameHost, emitter }) => {
|
|
2
|
-
let teardownWebNavigation = undefined;
|
|
3
|
-
let backCb = null;
|
|
4
|
-
return {
|
|
5
|
-
visible: false,
|
|
6
|
-
get onback() {
|
|
7
|
-
return backCb;
|
|
8
|
-
},
|
|
9
|
-
set onback(cb) {
|
|
10
|
-
if (backCb) {
|
|
11
|
-
emitter.removeListener('backNavigationTriggered', backCb);
|
|
12
|
-
}
|
|
13
|
-
backCb = cb;
|
|
14
|
-
if (cb) {
|
|
15
|
-
emitter.addListener('backNavigationTriggered', cb);
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
async show() {
|
|
19
|
-
await frameHost.updateBackState({
|
|
20
|
-
visible: true,
|
|
21
|
-
});
|
|
22
|
-
this.visible = true;
|
|
23
|
-
},
|
|
24
|
-
async hide() {
|
|
25
|
-
await frameHost.updateBackState({
|
|
26
|
-
visible: false,
|
|
27
|
-
});
|
|
28
|
-
this.visible = false;
|
|
29
|
-
},
|
|
30
|
-
async enableWebNavigation() {
|
|
31
|
-
teardownWebNavigation = setupWebBack({
|
|
32
|
-
back: this,
|
|
33
|
-
emitter,
|
|
34
|
-
});
|
|
35
|
-
},
|
|
36
|
-
async disableWebNavigation() {
|
|
37
|
-
teardownWebNavigation?.();
|
|
38
|
-
teardownWebNavigation = undefined;
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
function setupWebBack({ emitter, back, }) {
|
|
43
|
-
const navigation = getWebNavigation();
|
|
44
|
-
if (navigation) {
|
|
45
|
-
return setupNavigationApi({ emitter, back, navigation });
|
|
46
|
-
}
|
|
47
|
-
if (typeof window !== 'undefined') {
|
|
48
|
-
return setupFallback({ emitter, back, window });
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function getWebNavigation() {
|
|
52
|
-
if (typeof window !== 'undefined' && window.navigation !== undefined) {
|
|
53
|
-
return window.navigation;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
function setupNavigationApi({ emitter, back, navigation, }) {
|
|
57
|
-
function handleNavigateSuccess() {
|
|
58
|
-
if (navigation.canGoBack) {
|
|
59
|
-
back.show();
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
back.hide();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
function handleBackNavigationTriggered() {
|
|
66
|
-
if (back.visible && navigation.canGoBack) {
|
|
67
|
-
navigation.back();
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
navigation.addEventListener('navigatesuccess', handleNavigateSuccess);
|
|
71
|
-
emitter.addListener('backNavigationTriggered', handleBackNavigationTriggered);
|
|
72
|
-
return () => {
|
|
73
|
-
navigation.removeEventListener('navigatesuccess', handleNavigateSuccess);
|
|
74
|
-
emitter.removeListener('backNavigationTriggered', handleBackNavigationTriggered);
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
function setupFallback({ emitter, back, window, }) {
|
|
78
|
-
back.show();
|
|
79
|
-
function handleBackNavigationTriggered() {
|
|
80
|
-
if (back.visible) {
|
|
81
|
-
window.history.back();
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
emitter.addListener('backNavigationTriggered', handleBackNavigationTriggered);
|
|
85
|
-
return () => {
|
|
86
|
-
emitter.removeListener('backNavigationTriggered', handleBackNavigationTriggered);
|
|
87
|
-
};
|
|
88
|
-
}
|
package/dist/endpoint.d.ts
DELETED
package/dist/endpoint.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { windowEndpoint } from 'comlink';
|
|
2
|
-
const mockEndpoint = {
|
|
3
|
-
postMessage() {
|
|
4
|
-
// noop
|
|
5
|
-
},
|
|
6
|
-
addEventListener: () => {
|
|
7
|
-
// noop
|
|
8
|
-
},
|
|
9
|
-
removeEventListener: () => {
|
|
10
|
-
// noop
|
|
11
|
-
},
|
|
12
|
-
};
|
|
13
|
-
const webViewEndpoint = {
|
|
14
|
-
postMessage: (data) => {
|
|
15
|
-
console.debug('[webview:req]', data);
|
|
16
|
-
window.ReactNativeWebView.postMessage(JSON.stringify(data));
|
|
17
|
-
},
|
|
18
|
-
addEventListener: (_, listener, ...args) => {
|
|
19
|
-
document.addEventListener('FarcasterFrameCallback', listener, ...args);
|
|
20
|
-
},
|
|
21
|
-
removeEventListener: (_, listener) => {
|
|
22
|
-
document.removeEventListener('FarcasterFrameCallback', listener);
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
export const endpoint = (() => {
|
|
26
|
-
// No actions are actually gonna take place during SSR, thus it's safe to return mocked endpoint
|
|
27
|
-
if (typeof window === 'undefined')
|
|
28
|
-
return mockEndpoint;
|
|
29
|
-
return window?.ReactNativeWebView
|
|
30
|
-
? webViewEndpoint
|
|
31
|
-
: windowEndpoint(window?.parent ?? window);
|
|
32
|
-
})();
|
package/dist/ethereumProvider.js
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import * as Provider from 'ox/Provider';
|
|
2
|
-
import * as RpcRequest from 'ox/RpcRequest';
|
|
3
|
-
import * as RpcResponse from 'ox/RpcResponse';
|
|
4
|
-
import { frameHost } from "./frameHost.js";
|
|
5
|
-
const emitter = Provider.createEmitter();
|
|
6
|
-
const store = RpcRequest.createStore();
|
|
7
|
-
function toProviderRpcError({ code, details, }) {
|
|
8
|
-
switch (code) {
|
|
9
|
-
case 4001:
|
|
10
|
-
return new Provider.UserRejectedRequestError();
|
|
11
|
-
case 4100:
|
|
12
|
-
return new Provider.UnauthorizedError();
|
|
13
|
-
case 4200:
|
|
14
|
-
return new Provider.UnsupportedMethodError();
|
|
15
|
-
case 4900:
|
|
16
|
-
return new Provider.DisconnectedError();
|
|
17
|
-
case 4901:
|
|
18
|
-
return new Provider.ChainDisconnectedError();
|
|
19
|
-
default:
|
|
20
|
-
return new Provider.ProviderRpcError(code, details ?? 'Unknown provider RPC error');
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
export const ethereumProvider = Provider.from({
|
|
24
|
-
...emitter,
|
|
25
|
-
async request(args) {
|
|
26
|
-
// @ts-expect-error
|
|
27
|
-
const request = store.prepare(args);
|
|
28
|
-
try {
|
|
29
|
-
const response = await frameHost
|
|
30
|
-
.ethProviderRequestV2(request)
|
|
31
|
-
.then((res) => RpcResponse.parse(res, { request, raw: true }));
|
|
32
|
-
if (response.error) {
|
|
33
|
-
throw toProviderRpcError(response.error);
|
|
34
|
-
}
|
|
35
|
-
return response.result;
|
|
36
|
-
}
|
|
37
|
-
catch (e) {
|
|
38
|
-
// ethProviderRequestV2 not supported, fall back to v1
|
|
39
|
-
if (e instanceof Error &&
|
|
40
|
-
e.message.match(/cannot read property 'apply'/i)) {
|
|
41
|
-
return await frameHost.ethProviderRequest(request);
|
|
42
|
-
}
|
|
43
|
-
if (e instanceof Provider.ProviderRpcError ||
|
|
44
|
-
e instanceof RpcResponse.BaseError) {
|
|
45
|
-
throw e;
|
|
46
|
-
}
|
|
47
|
-
throw new RpcResponse.InternalError({
|
|
48
|
-
message: e instanceof Error ? e.message : undefined,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
export async function getEthereumProvider() {
|
|
54
|
-
try {
|
|
55
|
-
const capabilities = await frameHost.getCapabilities();
|
|
56
|
-
if (!capabilities.includes('wallet.getEthereumProvider') &&
|
|
57
|
-
!capabilities.includes('wallet.getEvmProvider')) {
|
|
58
|
-
// We used getEvmProvider for a short period before getEthereumProvider.
|
|
59
|
-
// In case we're talking to an old host, we check the old key.
|
|
60
|
-
return undefined;
|
|
61
|
-
}
|
|
62
|
-
return ethereumProvider;
|
|
63
|
-
}
|
|
64
|
-
catch {
|
|
65
|
-
// If this is an old frame host that doesn't support getCapabilities,
|
|
66
|
-
// getEthereumProvider will assume that it's supported
|
|
67
|
-
return ethereumProvider;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
function announceEvmProvider(detail) {
|
|
71
|
-
const event = new CustomEvent('eip6963:announceProvider', { detail: Object.freeze(detail) });
|
|
72
|
-
window.dispatchEvent(event);
|
|
73
|
-
const handler = () => window.dispatchEvent(event);
|
|
74
|
-
window.addEventListener('eip6963:requestProvider', handler);
|
|
75
|
-
return () => window.removeEventListener('eip6963:requestProvider', handler);
|
|
76
|
-
}
|
|
77
|
-
// Required to pass SSR
|
|
78
|
-
if (typeof document !== 'undefined') {
|
|
79
|
-
// forward eip6963:requestProvider events to the host
|
|
80
|
-
document.addEventListener('eip6963:requestProvider', () => {
|
|
81
|
-
frameHost.eip6963RequestProvider();
|
|
82
|
-
});
|
|
83
|
-
// react native webview events
|
|
84
|
-
document.addEventListener('FarcasterFrameEthProviderEvent', (event) => {
|
|
85
|
-
if (event instanceof MessageEvent) {
|
|
86
|
-
const ethProviderEvent = event.data;
|
|
87
|
-
// @ts-expect-error
|
|
88
|
-
emitter.emit(ethProviderEvent.event, ...ethProviderEvent.params);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
document.addEventListener('FarcasterFrameEvent', (event) => {
|
|
92
|
-
if (event instanceof MessageEvent) {
|
|
93
|
-
const frameEvent = event.data;
|
|
94
|
-
if (frameEvent.event === 'eip6963:announceProvider') {
|
|
95
|
-
announceEvmProvider({
|
|
96
|
-
info: frameEvent.info,
|
|
97
|
-
provider: ethereumProvider,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
// Required to pass SSR
|
|
104
|
-
if (typeof window !== 'undefined') {
|
|
105
|
-
// forward eip6963:requestProvider events to the host
|
|
106
|
-
window.addEventListener('eip6963:requestProvider', () => {
|
|
107
|
-
frameHost.eip6963RequestProvider();
|
|
108
|
-
});
|
|
109
|
-
// web events
|
|
110
|
-
window.addEventListener('message', (event) => {
|
|
111
|
-
if (event instanceof MessageEvent) {
|
|
112
|
-
if (event.data.type === 'frameEthProviderEvent') {
|
|
113
|
-
const ethProviderEvent = event.data;
|
|
114
|
-
// @ts-expect-error
|
|
115
|
-
emitter.emit(ethProviderEvent.event, ...ethProviderEvent.params);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
window.addEventListener('message', (event) => {
|
|
120
|
-
if (event instanceof MessageEvent) {
|
|
121
|
-
if (event.data.type === 'frameEvent') {
|
|
122
|
-
const frameEvent = event.data.event;
|
|
123
|
-
if (frameEvent.event === 'eip6963:announceProvider') {
|
|
124
|
-
announceEvmProvider({
|
|
125
|
-
info: frameEvent.info,
|
|
126
|
-
provider: ethereumProvider,
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
}
|
package/dist/frameHost.d.ts
DELETED
package/dist/frameHost.js
DELETED
package/dist/quickAuth.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { SignIn } from '@farcaster/frame-core';
|
|
2
|
-
export declare namespace getToken {
|
|
3
|
-
type Options = {
|
|
4
|
-
/**
|
|
5
|
-
* Use a custom Quick Auth server, otherwise defaults to the public
|
|
6
|
-
* instance provided by Farcaster.
|
|
7
|
-
*
|
|
8
|
-
* @default https://auth.farcaster.xyz
|
|
9
|
-
*/
|
|
10
|
-
quickAuthServerOrigin?: string;
|
|
11
|
-
/**
|
|
12
|
-
* Acquire a new token even if one is already in memory and not expired.
|
|
13
|
-
*
|
|
14
|
-
* @default false
|
|
15
|
-
*/
|
|
16
|
-
force?: string;
|
|
17
|
-
};
|
|
18
|
-
type ReturnValue = {
|
|
19
|
-
token: string;
|
|
20
|
-
};
|
|
21
|
-
type ReturnType = Promise<ReturnValue>;
|
|
22
|
-
type ErrorType = SignIn.RejectedByUser | Error;
|
|
23
|
-
}
|
|
24
|
-
export type QuickAuth = {
|
|
25
|
-
/**
|
|
26
|
-
* Returns the session token if one is present and not expired.
|
|
27
|
-
*/
|
|
28
|
-
readonly token: string | undefined;
|
|
29
|
-
/**
|
|
30
|
-
* Get a Quick Auth JWT.
|
|
31
|
-
*
|
|
32
|
-
* If a token is already in memory and not expired it will be returned unless
|
|
33
|
-
* `force` is used. Otherwise a new token will be acquired.
|
|
34
|
-
*/
|
|
35
|
-
getToken: (options?: getToken.Options) => getToken.ReturnType;
|
|
36
|
-
/**
|
|
37
|
-
* Make an authenticated fetch request. The `Authorization` header will
|
|
38
|
-
* contain `Bearer ${token}` where token is a Quick Auth session token.
|
|
39
|
-
*/
|
|
40
|
-
fetch: typeof fetch;
|
|
41
|
-
};
|
|
42
|
-
export declare const quickAuth: QuickAuth;
|
package/dist/quickAuth.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { SignIn } from '@farcaster/frame-core';
|
|
2
|
-
import { decodeJwt } from '@farcaster/quick-auth/decodeJwt';
|
|
3
|
-
import { createLightClient } from '@farcaster/quick-auth/light';
|
|
4
|
-
import * as Siwe from 'ox/Siwe';
|
|
5
|
-
import { frameHost } from './frameHost.js';
|
|
6
|
-
export const quickAuth = (() => {
|
|
7
|
-
let current;
|
|
8
|
-
let pendingPromise = undefined;
|
|
9
|
-
async function getTokenInner(options) {
|
|
10
|
-
const quickAuthClient = createLightClient({
|
|
11
|
-
origin: options.quickAuthServerOrigin,
|
|
12
|
-
});
|
|
13
|
-
const { nonce } = await quickAuthClient.generateNonce();
|
|
14
|
-
const response = await frameHost.signIn({
|
|
15
|
-
nonce,
|
|
16
|
-
acceptAuthAddress: true,
|
|
17
|
-
});
|
|
18
|
-
if (response.result) {
|
|
19
|
-
const parsedSiwe = Siwe.parseMessage(response.result.message);
|
|
20
|
-
// The Farcaster Client rendering the Mini App will set the domain
|
|
21
|
-
// based on the URL it's rendering. It should always be set.
|
|
22
|
-
if (!parsedSiwe.domain) {
|
|
23
|
-
throw new Error('Missing domain on SIWE message');
|
|
24
|
-
}
|
|
25
|
-
const verifyResult = await quickAuthClient.verifySiwf({
|
|
26
|
-
domain: parsedSiwe.domain,
|
|
27
|
-
message: response.result.message,
|
|
28
|
-
signature: response.result.signature,
|
|
29
|
-
});
|
|
30
|
-
current = {
|
|
31
|
-
token: verifyResult.token,
|
|
32
|
-
payload: decodeJwt(verifyResult.token),
|
|
33
|
-
};
|
|
34
|
-
return verifyResult;
|
|
35
|
-
}
|
|
36
|
-
if (response.error.type === 'rejected_by_user') {
|
|
37
|
-
throw new SignIn.RejectedByUser();
|
|
38
|
-
}
|
|
39
|
-
throw new Error('Unreachable');
|
|
40
|
-
}
|
|
41
|
-
return {
|
|
42
|
-
get token() {
|
|
43
|
-
if (current &&
|
|
44
|
-
new Date(current.payload.exp * 1000) > new Date(Date.now() + 15000)) {
|
|
45
|
-
return current.token;
|
|
46
|
-
}
|
|
47
|
-
return undefined;
|
|
48
|
-
},
|
|
49
|
-
async getToken(options = {}) {
|
|
50
|
-
const force = options.force ?? false;
|
|
51
|
-
if (current &&
|
|
52
|
-
!force &&
|
|
53
|
-
new Date(current.payload.exp * 1000) > new Date(Date.now() + 15000)) {
|
|
54
|
-
return { token: current.token };
|
|
55
|
-
}
|
|
56
|
-
if (!pendingPromise) {
|
|
57
|
-
pendingPromise = getTokenInner(options);
|
|
58
|
-
}
|
|
59
|
-
pendingPromise.finally(() => {
|
|
60
|
-
pendingPromise = undefined;
|
|
61
|
-
});
|
|
62
|
-
return pendingPromise;
|
|
63
|
-
},
|
|
64
|
-
async fetch(url, options) {
|
|
65
|
-
const { token } = await this.getToken();
|
|
66
|
-
const headers = new Headers(options?.headers);
|
|
67
|
-
headers.set('Authorization', `Bearer ${token}`);
|
|
68
|
-
return fetch(url, {
|
|
69
|
-
...options,
|
|
70
|
-
headers,
|
|
71
|
-
});
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
})();
|
package/dist/sdk.d.ts
DELETED
package/dist/sdk.js
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import { AddMiniApp, SignIn, } from '@farcaster/frame-core';
|
|
2
|
-
import { createBack } from "./back.js";
|
|
3
|
-
import { ethereumProvider, getEthereumProvider } from "./ethereumProvider.js";
|
|
4
|
-
import { frameHost } from "./frameHost.js";
|
|
5
|
-
import { quickAuth } from "./quickAuth.js";
|
|
6
|
-
import { emitter } from "./sdkEmitter.js";
|
|
7
|
-
import { getSolanaProvider } from "./solanaProvider.js";
|
|
8
|
-
let cachedIsInMiniAppResult = null;
|
|
9
|
-
/**
|
|
10
|
-
* Determines if the current environment is a MiniApp context.
|
|
11
|
-
*
|
|
12
|
-
* @param timeoutMs - Optional timeout in milliseconds (default: 50)
|
|
13
|
-
* @returns Promise resolving to boolean indicating if in MiniApp context
|
|
14
|
-
*/
|
|
15
|
-
async function isInMiniApp(timeoutMs = 50) {
|
|
16
|
-
// Return cached result if we've already determined we are in a MiniApp
|
|
17
|
-
if (cachedIsInMiniAppResult === true) {
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
20
|
-
// Check for SSR environment - definitely not a MiniApp
|
|
21
|
-
if (typeof window === 'undefined') {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
// Short-circuit: definitely NOT a MiniApp
|
|
25
|
-
if (!window.ReactNativeWebView && window === window.parent) {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
// At this point, we MIGHT be in a MiniApp (iframe or RN WebView)
|
|
29
|
-
// but need to verify by checking for context communication.
|
|
30
|
-
const isInMiniApp = await Promise.race([
|
|
31
|
-
frameHost.context.then((context) => !!context), // Check if context resolves to truthy
|
|
32
|
-
new Promise((resolve) => {
|
|
33
|
-
setTimeout(() => resolve(false), timeoutMs); // Timeout resolves to false
|
|
34
|
-
}),
|
|
35
|
-
]).catch(() => {
|
|
36
|
-
return false;
|
|
37
|
-
});
|
|
38
|
-
// Cache the result ONLY if true (we are confirmed to be in a MiniApp)
|
|
39
|
-
if (isInMiniApp) {
|
|
40
|
-
cachedIsInMiniAppResult = true;
|
|
41
|
-
}
|
|
42
|
-
return isInMiniApp;
|
|
43
|
-
}
|
|
44
|
-
const addMiniApp = async () => {
|
|
45
|
-
const response = await frameHost.addFrame();
|
|
46
|
-
if (response.result) {
|
|
47
|
-
return response.result;
|
|
48
|
-
}
|
|
49
|
-
if (response.error.type === 'invalid_domain_manifest') {
|
|
50
|
-
throw new AddMiniApp.InvalidDomainManifest();
|
|
51
|
-
}
|
|
52
|
-
if (response.error.type === 'rejected_by_user') {
|
|
53
|
-
throw new AddMiniApp.RejectedByUser();
|
|
54
|
-
}
|
|
55
|
-
throw new Error('Unreachable');
|
|
56
|
-
};
|
|
57
|
-
export const sdk = {
|
|
58
|
-
...emitter,
|
|
59
|
-
getCapabilities: frameHost.getCapabilities,
|
|
60
|
-
getChains: frameHost.getChains,
|
|
61
|
-
isInMiniApp,
|
|
62
|
-
context: frameHost.context,
|
|
63
|
-
back: createBack({ frameHost, emitter }),
|
|
64
|
-
quickAuth,
|
|
65
|
-
actions: {
|
|
66
|
-
setPrimaryButton: frameHost.setPrimaryButton.bind(frameHost),
|
|
67
|
-
ready: async (options = {}) => {
|
|
68
|
-
return await frameHost.ready(options);
|
|
69
|
-
},
|
|
70
|
-
close: frameHost.close.bind(frameHost),
|
|
71
|
-
viewCast: frameHost.viewCast.bind(frameHost),
|
|
72
|
-
viewProfile: frameHost.viewProfile.bind(frameHost),
|
|
73
|
-
signIn: async (options) => {
|
|
74
|
-
const response = await frameHost.signIn(options);
|
|
75
|
-
if (response.result) {
|
|
76
|
-
return response.result;
|
|
77
|
-
}
|
|
78
|
-
if (response.error.type === 'rejected_by_user') {
|
|
79
|
-
throw new SignIn.RejectedByUser();
|
|
80
|
-
}
|
|
81
|
-
throw new Error('Unreachable');
|
|
82
|
-
},
|
|
83
|
-
openUrl: (urlArg) => {
|
|
84
|
-
const url = typeof urlArg === 'string' ? urlArg : urlArg.url;
|
|
85
|
-
return frameHost.openUrl(url.trim());
|
|
86
|
-
},
|
|
87
|
-
addFrame: addMiniApp,
|
|
88
|
-
addMiniApp,
|
|
89
|
-
composeCast(options = {}) {
|
|
90
|
-
return frameHost.composeCast(options);
|
|
91
|
-
},
|
|
92
|
-
viewToken: frameHost.viewToken.bind(frameHost),
|
|
93
|
-
sendToken: frameHost.sendToken.bind(frameHost),
|
|
94
|
-
swapToken: frameHost.swapToken.bind(frameHost),
|
|
95
|
-
},
|
|
96
|
-
experimental: {
|
|
97
|
-
getSolanaProvider,
|
|
98
|
-
quickAuth(options) {
|
|
99
|
-
return quickAuth.getToken(options);
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
wallet: {
|
|
103
|
-
ethProvider: ethereumProvider,
|
|
104
|
-
getEthereumProvider,
|
|
105
|
-
getSolanaProvider,
|
|
106
|
-
},
|
|
107
|
-
haptics: {
|
|
108
|
-
impactOccurred: frameHost.impactOccurred.bind(frameHost),
|
|
109
|
-
notificationOccurred: frameHost.notificationOccurred.bind(frameHost),
|
|
110
|
-
selectionChanged: frameHost.selectionChanged.bind(frameHost),
|
|
111
|
-
},
|
|
112
|
-
};
|
|
113
|
-
// Required to pass SSR
|
|
114
|
-
if (typeof document !== 'undefined') {
|
|
115
|
-
// react native webview events
|
|
116
|
-
document.addEventListener('FarcasterFrameEvent', (event) => {
|
|
117
|
-
if (event instanceof MessageEvent) {
|
|
118
|
-
const frameEvent = event.data;
|
|
119
|
-
if (frameEvent.event === 'primary_button_clicked') {
|
|
120
|
-
emitter.emit('primaryButtonClicked');
|
|
121
|
-
}
|
|
122
|
-
else if (frameEvent.event === 'frame_added') {
|
|
123
|
-
emitter.emit('frameAdded', {
|
|
124
|
-
notificationDetails: frameEvent.notificationDetails,
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
else if (frameEvent.event === 'frame_add_rejected') {
|
|
128
|
-
emitter.emit('frameAddRejected', { reason: frameEvent.reason });
|
|
129
|
-
}
|
|
130
|
-
else if (frameEvent.event === 'frame_removed') {
|
|
131
|
-
emitter.emit('frameRemoved');
|
|
132
|
-
}
|
|
133
|
-
else if (frameEvent.event === 'notifications_enabled') {
|
|
134
|
-
emitter.emit('notificationsEnabled', {
|
|
135
|
-
notificationDetails: frameEvent.notificationDetails,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
else if (frameEvent.event === 'notifications_disabled') {
|
|
139
|
-
emitter.emit('notificationsDisabled');
|
|
140
|
-
}
|
|
141
|
-
else if (frameEvent.event === 'back_navigation_triggered') {
|
|
142
|
-
emitter.emit('backNavigationTriggered');
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
// Required to pass SSR
|
|
148
|
-
if (typeof window !== 'undefined') {
|
|
149
|
-
// web events
|
|
150
|
-
window.addEventListener('message', (event) => {
|
|
151
|
-
if (event instanceof MessageEvent) {
|
|
152
|
-
if (event.data.type === 'frameEvent') {
|
|
153
|
-
const frameEvent = event.data.event;
|
|
154
|
-
if (frameEvent.event === 'primary_button_clicked') {
|
|
155
|
-
emitter.emit('primaryButtonClicked');
|
|
156
|
-
}
|
|
157
|
-
else if (frameEvent.event === 'frame_added') {
|
|
158
|
-
emitter.emit('frameAdded', {
|
|
159
|
-
notificationDetails: frameEvent.notificationDetails,
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
else if (frameEvent.event === 'frame_add_rejected') {
|
|
163
|
-
emitter.emit('frameAddRejected', { reason: frameEvent.reason });
|
|
164
|
-
}
|
|
165
|
-
else if (frameEvent.event === 'frame_removed') {
|
|
166
|
-
emitter.emit('frameRemoved');
|
|
167
|
-
}
|
|
168
|
-
else if (frameEvent.event === 'notifications_enabled') {
|
|
169
|
-
emitter.emit('notificationsEnabled', {
|
|
170
|
-
notificationDetails: frameEvent.notificationDetails,
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
else if (frameEvent.event === 'notifications_disabled') {
|
|
174
|
-
emitter.emit('notificationsDisabled');
|
|
175
|
-
}
|
|
176
|
-
else if (frameEvent.event === 'back_navigation_triggered') {
|
|
177
|
-
emitter.emit('backNavigationTriggered');
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
}
|