@farcaster/frame-wagmi-connector 0.0.1

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/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # Frame Wagmi Connector
2
+
3
+ A [Wagmi connector](https://wagmi.sh/) for Farcaster frames.
4
+
5
+ Not yet stable. [Learn more](https://github.com/farcasterxyz/frames/wiki/frames-v2-developer-playground-preview).
6
+
7
+ ## Install
8
+
9
+ Install using your favorite manager:
10
+
11
+ ```
12
+ npm install @farcaster/frame-connector
13
+ ```
@@ -0,0 +1,444 @@
1
+ export declare function farcasterFrame(): import("wagmi").CreateConnectorFn<{
2
+ request: import("ox/Provider").RequestFn<{
3
+ Request: {
4
+ method: "eth_accounts";
5
+ params?: undefined;
6
+ };
7
+ ReturnType: readonly import("ox/Address").Address[];
8
+ } | {
9
+ Request: {
10
+ method: "eth_blobBaseFee";
11
+ params?: undefined;
12
+ };
13
+ ReturnType: import("ox/Hex").Hex;
14
+ } | {
15
+ Request: {
16
+ method: "eth_blockNumber";
17
+ params?: undefined;
18
+ };
19
+ ReturnType: import("ox/Hex").Hex;
20
+ } | {
21
+ Request: {
22
+ method: "eth_call";
23
+ params: [transaction: import("ox/TransactionRequest").Rpc] | [transaction: import("ox/TransactionRequest").Rpc, block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag | import("ox/Block").Hash | import("ox/Block").Identifier] | [transaction: import("ox/TransactionRequest").Rpc, block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag | import("ox/Block").Hash | import("ox/Block").Identifier, stateOverride: unknown];
24
+ };
25
+ ReturnType: import("ox/Hex").Hex;
26
+ } | {
27
+ Request: {
28
+ method: "eth_chainId";
29
+ params?: undefined;
30
+ };
31
+ ReturnType: import("ox/Hex").Hex;
32
+ } | {
33
+ Request: {
34
+ method: "eth_coinbase";
35
+ params?: undefined;
36
+ };
37
+ ReturnType: import("ox/Address").Address;
38
+ } | {
39
+ Request: {
40
+ method: "eth_estimateGas";
41
+ params: [transaction: import("ox/TransactionRequest").Rpc] | [transaction: import("ox/TransactionRequest").Rpc, block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag | import("ox/Block").Hash | import("ox/Block").Identifier] | [transaction: import("ox/TransactionRequest").Rpc, block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag | import("ox/Block").Hash | import("ox/Block").Identifier, stateOverride: unknown];
42
+ };
43
+ ReturnType: import("ox/Hex").Hex;
44
+ } | {
45
+ Request: {
46
+ method: "eth_feeHistory";
47
+ params: [blockCount: import("ox/Hex").Hex, newestBlock: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag, rewardPercentiles: number[] | undefined];
48
+ };
49
+ ReturnType: import("ox/Fee").FeeHistoryRpc;
50
+ } | {
51
+ Request: {
52
+ method: "eth_gasPrice";
53
+ params?: undefined;
54
+ };
55
+ ReturnType: import("ox/Hex").Hex;
56
+ } | {
57
+ Request: {
58
+ method: "eth_getBalance";
59
+ params: [address: import("ox/Address").Address, block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag | import("ox/Block").Hash | import("ox/Block").Identifier];
60
+ };
61
+ ReturnType: import("ox/Hex").Hex;
62
+ } | {
63
+ Request: {
64
+ method: "eth_getBlockByHash";
65
+ params: [hash: import("ox/Hex").Hex, includeTransactionObjects: boolean];
66
+ };
67
+ ReturnType: import("ox/Block").Rpc | null;
68
+ } | {
69
+ Request: {
70
+ method: "eth_getBlockByNumber";
71
+ params: [block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag, includeTransactionObjects: boolean];
72
+ };
73
+ ReturnType: import("ox/Block").Rpc | null;
74
+ } | {
75
+ Request: {
76
+ method: "eth_getBlockTransactionCountByHash";
77
+ params: [hash: import("ox/Hex").Hex];
78
+ };
79
+ ReturnType: import("ox/Hex").Hex;
80
+ } | {
81
+ Request: {
82
+ method: "eth_getBlockTransactionCountByNumber";
83
+ params: [block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag];
84
+ };
85
+ ReturnType: import("ox/Hex").Hex;
86
+ } | {
87
+ Request: {
88
+ method: "eth_getCode";
89
+ params: [address: import("ox/Address").Address, block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag | import("ox/Block").Hash | import("ox/Block").Identifier];
90
+ };
91
+ ReturnType: import("ox/Hex").Hex;
92
+ } | {
93
+ Request: {
94
+ method: "eth_getFilterChanges";
95
+ params: [filterId: import("ox/Hex").Hex];
96
+ };
97
+ ReturnType: readonly import("ox/Log").Rpc[] | readonly import("ox/Hex").Hex[];
98
+ } | {
99
+ Request: {
100
+ method: "eth_getFilterLogs";
101
+ params: [filterId: import("ox/Hex").Hex];
102
+ };
103
+ ReturnType: readonly import("ox/Log").Rpc[];
104
+ } | {
105
+ Request: {
106
+ method: "eth_getLogs";
107
+ params: [filter: import("ox/Filter").Rpc];
108
+ };
109
+ ReturnType: readonly import("ox/Log").Rpc[];
110
+ } | {
111
+ Request: {
112
+ method: "eth_getProof";
113
+ params: [address: import("ox/Address").Address, storageKeys: import("ox/Hex").Hex[], block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag | import("ox/Block").Hash | import("ox/Block").Identifier];
114
+ };
115
+ ReturnType: import("ox/AccountProof").Rpc;
116
+ } | {
117
+ Request: {
118
+ method: "eth_getStorageAt";
119
+ params: [address: import("ox/Address").Address, index: import("ox/Hex").Hex, block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag | import("ox/Block").Hash | import("ox/Block").Identifier];
120
+ };
121
+ ReturnType: import("ox/Hex").Hex;
122
+ } | {
123
+ Request: {
124
+ method: "eth_getTransactionByBlockHashAndIndex";
125
+ params: [hash: import("ox/Hex").Hex, index: import("ox/Hex").Hex];
126
+ };
127
+ ReturnType: import("ox/Transaction").Rpc | null;
128
+ } | {
129
+ Request: {
130
+ method: "eth_getTransactionByBlockNumberAndIndex";
131
+ params: [block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag, index: import("ox/Hex").Hex];
132
+ };
133
+ ReturnType: import("ox/Transaction").Rpc | null;
134
+ } | {
135
+ Request: {
136
+ method: "eth_getTransactionByHash";
137
+ params: [hash: import("ox/Hex").Hex];
138
+ };
139
+ ReturnType: import("ox/Transaction").Rpc | null;
140
+ } | {
141
+ Request: {
142
+ method: "eth_getTransactionCount";
143
+ params: [address: import("ox/Address").Address, block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag | import("ox/Block").Hash | import("ox/Block").Identifier];
144
+ };
145
+ ReturnType: import("ox/Hex").Hex;
146
+ } | {
147
+ Request: {
148
+ method: "eth_getTransactionReceipt";
149
+ params: [hash: import("ox/Hex").Hex];
150
+ };
151
+ ReturnType: import("ox/TransactionReceipt").Rpc | null;
152
+ } | {
153
+ Request: {
154
+ method: "eth_getUncleCountByBlockHash";
155
+ params: [hash: import("ox/Hex").Hex];
156
+ };
157
+ ReturnType: import("ox/Hex").Hex;
158
+ } | {
159
+ Request: {
160
+ method: "eth_getUncleCountByBlockNumber";
161
+ params: [block: import("ox/Block").Number<import("ox/Hex").Hex> | import("ox/Block").Tag];
162
+ };
163
+ ReturnType: import("ox/Hex").Hex;
164
+ } | {
165
+ Request: {
166
+ method: "eth_maxPriorityFeePerGas";
167
+ params?: undefined;
168
+ };
169
+ ReturnType: import("ox/Hex").Hex;
170
+ } | {
171
+ Request: {
172
+ method: "eth_newBlockFilter";
173
+ params?: undefined;
174
+ };
175
+ ReturnType: import("ox/Hex").Hex;
176
+ } | {
177
+ Request: {
178
+ method: "eth_newFilter";
179
+ params: [filter: import("ox/Filter").Rpc];
180
+ };
181
+ ReturnType: import("ox/Hex").Hex;
182
+ } | {
183
+ Request: {
184
+ method: "eth_newPendingTransactionFilter";
185
+ params?: undefined;
186
+ };
187
+ ReturnType: import("ox/Hex").Hex;
188
+ } | {
189
+ Request: {
190
+ method: "eth_protocolVersion";
191
+ params?: undefined;
192
+ };
193
+ ReturnType: string;
194
+ } | {
195
+ Request: {
196
+ method: "eth_requestAccounts";
197
+ params?: undefined;
198
+ };
199
+ ReturnType: readonly import("ox/Address").Address[];
200
+ } | {
201
+ Request: {
202
+ method: "eth_sendRawTransaction";
203
+ params: [serializedTransaction: import("ox/Hex").Hex];
204
+ };
205
+ ReturnType: import("ox/Hex").Hex;
206
+ } | {
207
+ Request: {
208
+ method: "eth_sendTransaction";
209
+ params: [transaction: import("ox/TransactionRequest").Rpc];
210
+ };
211
+ ReturnType: import("ox/Hex").Hex;
212
+ } | {
213
+ Request: {
214
+ method: "eth_signTransaction";
215
+ params: [request: import("ox/TransactionRequest").Rpc];
216
+ };
217
+ ReturnType: import("ox/Hex").Hex;
218
+ } | {
219
+ Request: {
220
+ method: "eth_signTypedData_v4";
221
+ params: [address: import("ox/Address").Address, message: string];
222
+ };
223
+ ReturnType: import("ox/Hex").Hex;
224
+ } | {
225
+ Request: {
226
+ method: "eth_uninstallFilter";
227
+ params: [filterId: import("ox/Hex").Hex];
228
+ };
229
+ ReturnType: boolean;
230
+ } | {
231
+ Request: {
232
+ method: "eth_requestAccounts";
233
+ params?: undefined;
234
+ };
235
+ ReturnType: readonly import("ox/Address").Address[];
236
+ } | {
237
+ Request: {
238
+ method: "eth_sendRawTransaction";
239
+ params: [serializedTransaction: import("ox/Hex").Hex];
240
+ };
241
+ ReturnType: import("ox/Hex").Hex;
242
+ } | {
243
+ Request: {
244
+ method: "eth_sendTransaction";
245
+ params: [transaction: import("ox/TransactionRequest").Rpc];
246
+ };
247
+ ReturnType: import("ox/Hex").Hex;
248
+ } | {
249
+ Request: {
250
+ method: "eth_signTransaction";
251
+ params: [request: import("ox/TransactionRequest").Rpc];
252
+ };
253
+ ReturnType: import("ox/Hex").Hex;
254
+ } | {
255
+ Request: {
256
+ method: "eth_signTypedData_v4";
257
+ params: [address: import("ox/Address").Address, message: string];
258
+ };
259
+ ReturnType: import("ox/Hex").Hex;
260
+ } | {
261
+ Request: {
262
+ method: "personal_sign";
263
+ params: [data: import("ox/Hex").Hex, address: import("ox/Address").Address];
264
+ };
265
+ ReturnType: import("ox/Hex").Hex;
266
+ } | {
267
+ Request: {
268
+ method: "wallet_addEthereumChain";
269
+ params: [chain: {
270
+ chainId: string;
271
+ chainName: string;
272
+ nativeCurrency?: {
273
+ name: string;
274
+ symbol: string;
275
+ decimals: number;
276
+ } | undefined | undefined;
277
+ rpcUrls: readonly string[];
278
+ blockExplorerUrls?: readonly string[] | undefined;
279
+ iconUrls?: readonly string[] | undefined;
280
+ }];
281
+ };
282
+ ReturnType: null;
283
+ } | {
284
+ Request: {
285
+ method: "wallet_getCallsStatus";
286
+ params?: [string];
287
+ };
288
+ ReturnType: {
289
+ status: "PENDING" | "CONFIRMED";
290
+ receipts?: readonly {
291
+ logs: {
292
+ address: import("ox/Hex").Hex;
293
+ data: import("ox/Hex").Hex;
294
+ topics: readonly import("ox/Hex").Hex[];
295
+ }[];
296
+ status: import("ox/Hex").Hex;
297
+ blockHash: import("ox/Hex").Hex;
298
+ blockNumber: import("ox/Hex").Hex;
299
+ gasUsed: import("ox/Hex").Hex;
300
+ transactionHash: import("ox/Hex").Hex;
301
+ }[] | undefined;
302
+ };
303
+ } | {
304
+ Request: {
305
+ method: "wallet_getCapabilities";
306
+ params?: [import("ox/Address").Address];
307
+ };
308
+ ReturnType: {
309
+ [x: `0x${string}`]: {
310
+ [capability: string]: any;
311
+ };
312
+ };
313
+ } | {
314
+ Request: {
315
+ method: "wallet_getPermissions";
316
+ params?: undefined;
317
+ };
318
+ ReturnType: readonly {
319
+ caveats: readonly {
320
+ type: string;
321
+ value: any;
322
+ }[];
323
+ date: number;
324
+ id: string;
325
+ invoker: `http://${string}` | `https://${string}`;
326
+ parentCapability: "eth_accounts" | string;
327
+ }[];
328
+ } | {
329
+ Request: {
330
+ method: "wallet_grantPermissions";
331
+ params?: [{
332
+ signer?: {
333
+ type: string;
334
+ data?: unknown | undefined;
335
+ } | undefined;
336
+ permissions: readonly {
337
+ data: unknown;
338
+ policies: readonly {
339
+ data: unknown;
340
+ type: string;
341
+ }[];
342
+ required?: boolean | undefined;
343
+ type: string;
344
+ }[];
345
+ expiry: number;
346
+ }];
347
+ };
348
+ ReturnType: {
349
+ expiry: number;
350
+ factory?: `0x${string}` | undefined | undefined;
351
+ factoryData?: string | undefined | undefined;
352
+ grantedPermissions: readonly {
353
+ data: unknown;
354
+ policies: readonly {
355
+ data: unknown;
356
+ type: string;
357
+ }[];
358
+ required?: boolean | undefined;
359
+ type: string;
360
+ }[];
361
+ permissionsContext: string;
362
+ signerData?: {
363
+ userOpBuilder?: `0x${string}` | undefined;
364
+ submitToAddress?: `0x${string}` | undefined;
365
+ } | undefined | undefined;
366
+ };
367
+ } | {
368
+ Request: {
369
+ method: "wallet_requestPermissions";
370
+ params: [permissions: {
371
+ eth_accounts: Record<string, any>;
372
+ }];
373
+ };
374
+ ReturnType: readonly {
375
+ caveats: readonly {
376
+ type: string;
377
+ value: any;
378
+ }[];
379
+ date: number;
380
+ id: string;
381
+ invoker: `http://${string}` | `https://${string}`;
382
+ parentCapability: "eth_accounts" | string;
383
+ }[];
384
+ } | {
385
+ Request: {
386
+ method: "wallet_revokePermissions";
387
+ params: [permissions: {
388
+ eth_accounts: Record<string, any>;
389
+ }];
390
+ };
391
+ ReturnType: null;
392
+ } | {
393
+ Request: {
394
+ method: "wallet_sendCalls";
395
+ params: [{
396
+ calls: readonly {
397
+ to?: import("ox/Address").Address | undefined;
398
+ data?: import("ox/Hex").Hex | undefined;
399
+ value?: import("ox/Hex").Hex | undefined;
400
+ }[];
401
+ capabilities?: {
402
+ [capability: string]: any;
403
+ } | undefined;
404
+ chainId?: import("ox/Hex").Hex | undefined;
405
+ from: import("ox/Address").Address;
406
+ version: string;
407
+ }];
408
+ };
409
+ ReturnType: string;
410
+ } | {
411
+ Request: {
412
+ method: "wallet_showCallsStatus";
413
+ params: [string];
414
+ };
415
+ ReturnType: undefined;
416
+ } | {
417
+ Request: {
418
+ method: "wallet_switchEthereumChain";
419
+ params: [chain: {
420
+ chainId: string;
421
+ }];
422
+ };
423
+ ReturnType: null;
424
+ } | {
425
+ Request: {
426
+ method: "wallet_watchAsset";
427
+ params: [{
428
+ type: "ERC20";
429
+ options: {
430
+ address: string;
431
+ symbol: string;
432
+ decimals: number;
433
+ image?: string | undefined;
434
+ };
435
+ }];
436
+ };
437
+ ReturnType: boolean;
438
+ }>;
439
+ on: import("ox/Provider").EventListenerFn;
440
+ removeListener: import("ox/Provider").EventListenerFn;
441
+ }, Record<string, unknown>, Record<string, unknown>>;
442
+ export declare namespace farcasterFrame {
443
+ var type: "farcasterFrame";
444
+ }
@@ -0,0 +1,126 @@
1
+ import FrameSDK from '@farcaster/frame-sdk';
2
+ import { SwitchChainError, fromHex, getAddress, numberToHex } from 'viem';
3
+ import { ChainNotConfiguredError, createConnector } from 'wagmi';
4
+ farcasterFrame.type = 'farcasterFrame';
5
+ let accountsChanged;
6
+ let chainChanged;
7
+ let disconnect;
8
+ export function farcasterFrame() {
9
+ let connected = true;
10
+ return createConnector((config) => ({
11
+ id: 'farcaster',
12
+ name: 'Farcaster Frame',
13
+ rdns: 'xyz.farcaster',
14
+ icon: 'https://imagedelivery.net/BXluQx4ige9GuW0Ia56BHw/055c25d6-7fe7-4a49-abf9-49772021cf00/original',
15
+ type: farcasterFrame.type,
16
+ async setup() {
17
+ this.connect({ chainId: config.chains[0].id });
18
+ },
19
+ async connect({ chainId } = {}) {
20
+ const provider = await this.getProvider();
21
+ const accounts = await provider.request({
22
+ method: 'eth_requestAccounts',
23
+ });
24
+ if (!accountsChanged) {
25
+ accountsChanged = this.onAccountsChanged.bind(this);
26
+ // @ts-expect-error - provider type is stricter
27
+ provider.on('accountsChanged', accountsChanged);
28
+ }
29
+ if (!chainChanged) {
30
+ chainChanged = this.onChainChanged.bind(this);
31
+ provider.on('chainChanged', chainChanged);
32
+ }
33
+ if (!disconnect) {
34
+ disconnect = this.onDisconnect.bind(this);
35
+ provider.on('disconnect', disconnect);
36
+ }
37
+ let currentChainId = await this.getChainId();
38
+ if (chainId && currentChainId !== chainId) {
39
+ const chain = await this.switchChain({ chainId });
40
+ currentChainId = chain.id;
41
+ }
42
+ connected = true;
43
+ return {
44
+ accounts: accounts.map((x) => getAddress(x)),
45
+ chainId: currentChainId,
46
+ };
47
+ },
48
+ async disconnect() {
49
+ const provider = await this.getProvider();
50
+ if (accountsChanged) {
51
+ // @ts-expect-error - provider type is stricter
52
+ provider.removeListener('accountsChanged', accountsChanged);
53
+ accountsChanged = undefined;
54
+ }
55
+ if (chainChanged) {
56
+ provider.removeListener('chainChanged', chainChanged);
57
+ chainChanged = undefined;
58
+ }
59
+ if (disconnect) {
60
+ provider.removeListener('disconnect', disconnect);
61
+ disconnect = undefined;
62
+ }
63
+ connected = false;
64
+ },
65
+ async getAccounts() {
66
+ if (!connected) {
67
+ throw new Error('Not connected');
68
+ }
69
+ const provider = await this.getProvider();
70
+ const accounts = await provider.request({
71
+ method: 'eth_requestAccounts',
72
+ });
73
+ return accounts.map((x) => getAddress(x));
74
+ },
75
+ async getChainId() {
76
+ const provider = await this.getProvider();
77
+ const hexChainId = await provider.request({ method: 'eth_chainId' });
78
+ return fromHex(hexChainId, 'number');
79
+ },
80
+ async isAuthorized() {
81
+ if (!connected) {
82
+ return false;
83
+ }
84
+ const accounts = await this.getAccounts();
85
+ return !!accounts.length;
86
+ },
87
+ async switchChain({ chainId }) {
88
+ const provider = await this.getProvider();
89
+ const chain = config.chains.find((x) => x.id === chainId);
90
+ if (!chain) {
91
+ throw new SwitchChainError(new ChainNotConfiguredError());
92
+ }
93
+ await provider.request({
94
+ method: 'wallet_switchEthereumChain',
95
+ params: [{ chainId: numberToHex(chainId) }],
96
+ });
97
+ // providers should start emitting these events - remove when hosts have upgraded
98
+ //
99
+ // explicitly emit this event as a workaround for ethereum provider not
100
+ // emitting events, can remove once events are flowing
101
+ config.emitter.emit('change', { chainId });
102
+ return chain;
103
+ },
104
+ onAccountsChanged(accounts) {
105
+ if (accounts.length === 0) {
106
+ this.onDisconnect();
107
+ }
108
+ else {
109
+ config.emitter.emit('change', {
110
+ accounts: accounts.map((x) => getAddress(x)),
111
+ });
112
+ }
113
+ },
114
+ onChainChanged(chain) {
115
+ const chainId = Number(chain);
116
+ config.emitter.emit('change', { chainId });
117
+ },
118
+ async onDisconnect() {
119
+ config.emitter.emit('disconnect');
120
+ connected = false;
121
+ },
122
+ async getProvider() {
123
+ return FrameSDK.wallet.ethProvider;
124
+ },
125
+ }));
126
+ }
@@ -0,0 +1,3 @@
1
+ import { farcasterFrame } from "./connector";
2
+ export * from "./connector";
3
+ export default farcasterFrame;
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { farcasterFrame } from "./connector";
2
+ export * from "./connector";
3
+ export default farcasterFrame;