accounts 0.3.0 → 0.4.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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +97 -0
- package/dist/core/AccessKey.d.ts +55 -0
- package/dist/core/AccessKey.d.ts.map +1 -0
- package/dist/core/AccessKey.js +69 -0
- package/dist/core/AccessKey.js.map +1 -0
- package/dist/core/Account.d.ts +91 -0
- package/dist/core/Account.d.ts.map +1 -0
- package/dist/core/Account.js +64 -0
- package/dist/core/Account.js.map +1 -0
- package/dist/core/Adapter.d.ts +187 -0
- package/dist/core/Adapter.d.ts.map +1 -0
- package/dist/core/Adapter.js +7 -0
- package/dist/core/Adapter.js.map +1 -0
- package/dist/core/Ceremony.d.ts +109 -0
- package/dist/core/Ceremony.d.ts.map +1 -0
- package/dist/core/Ceremony.js +104 -0
- package/dist/core/Ceremony.js.map +1 -0
- package/dist/core/Client.d.ts +16 -0
- package/dist/core/Client.d.ts.map +1 -0
- package/dist/core/Client.js +18 -0
- package/dist/core/Client.js.map +1 -0
- package/dist/core/Dialog.d.ts +52 -0
- package/dist/core/Dialog.d.ts.map +1 -0
- package/dist/core/Dialog.js +342 -0
- package/dist/core/Dialog.js.map +1 -0
- package/dist/core/Expiry.d.ts +15 -0
- package/dist/core/Expiry.d.ts.map +1 -0
- package/dist/core/Expiry.js +29 -0
- package/dist/core/Expiry.js.map +1 -0
- package/dist/core/Messenger.d.ts +86 -0
- package/dist/core/Messenger.d.ts.map +1 -0
- package/dist/core/Messenger.js +127 -0
- package/dist/core/Messenger.js.map +1 -0
- package/dist/core/Provider.d.ts +69 -0
- package/dist/core/Provider.d.ts.map +1 -0
- package/dist/core/Provider.js +401 -0
- package/dist/core/Provider.js.map +1 -0
- package/dist/core/Remote.d.ts +114 -0
- package/dist/core/Remote.d.ts.map +1 -0
- package/dist/core/Remote.js +116 -0
- package/dist/core/Remote.js.map +1 -0
- package/dist/core/Schema.d.ts +805 -0
- package/dist/core/Schema.d.ts.map +1 -0
- package/dist/core/Schema.js +43 -0
- package/dist/core/Schema.js.map +1 -0
- package/dist/core/Storage.d.ts +42 -0
- package/dist/core/Storage.d.ts.map +1 -0
- package/dist/core/Storage.js +173 -0
- package/dist/core/Storage.js.map +1 -0
- package/dist/core/Store.d.ts +58 -0
- package/dist/core/Store.d.ts.map +1 -0
- package/dist/core/Store.js +58 -0
- package/dist/core/Store.js.map +1 -0
- package/dist/core/adapters/dangerous_secp256k1.d.ts +30 -0
- package/dist/core/adapters/dangerous_secp256k1.d.ts.map +1 -0
- package/dist/core/adapters/dangerous_secp256k1.js +39 -0
- package/dist/core/adapters/dangerous_secp256k1.js.map +1 -0
- package/dist/core/adapters/dialog.d.ts +31 -0
- package/dist/core/adapters/dialog.d.ts.map +1 -0
- package/dist/core/adapters/dialog.js +306 -0
- package/dist/core/adapters/dialog.js.map +1 -0
- package/dist/core/adapters/local.d.ts +33 -0
- package/dist/core/adapters/local.d.ts.map +1 -0
- package/dist/core/adapters/local.js +227 -0
- package/dist/core/adapters/local.js.map +1 -0
- package/dist/core/adapters/webAuthn.d.ts +36 -0
- package/dist/core/adapters/webAuthn.d.ts.map +1 -0
- package/dist/core/adapters/webAuthn.js +93 -0
- package/dist/core/adapters/webAuthn.js.map +1 -0
- package/dist/core/internal/withDedupe.d.ts +12 -0
- package/dist/core/internal/withDedupe.d.ts.map +1 -0
- package/dist/core/internal/withDedupe.js +12 -0
- package/dist/core/internal/withDedupe.js.map +1 -0
- package/dist/core/zod/request.d.ts +31 -0
- package/dist/core/zod/request.d.ts.map +1 -0
- package/dist/core/zod/request.js +41 -0
- package/dist/core/zod/request.js.map +1 -0
- package/dist/core/zod/rpc.d.ts +603 -0
- package/dist/core/zod/rpc.d.ts.map +1 -0
- package/dist/core/zod/rpc.js +293 -0
- package/dist/core/zod/rpc.js.map +1 -0
- package/dist/core/zod/utils.d.ts +18 -0
- package/dist/core/zod/utils.d.ts.map +1 -0
- package/dist/core/zod/utils.js +21 -0
- package/dist/core/zod/utils.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/types.d.ts +284 -0
- package/dist/internal/types.d.ts.map +1 -0
- package/dist/internal/types.js +2 -0
- package/dist/internal/types.js.map +1 -0
- package/dist/server/Handler.d.ts +257 -0
- package/dist/server/Handler.d.ts.map +1 -0
- package/dist/server/Handler.js +433 -0
- package/dist/server/Handler.js.map +1 -0
- package/dist/server/Kv.d.ts +16 -0
- package/dist/server/Kv.d.ts.map +1 -0
- package/dist/server/Kv.js +30 -0
- package/dist/server/Kv.js.map +1 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +3 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/internal/requestListener.d.ts +124 -0
- package/dist/server/internal/requestListener.d.ts.map +1 -0
- package/dist/server/internal/requestListener.js +173 -0
- package/dist/server/internal/requestListener.js.map +1 -0
- package/dist/wagmi/Connector.d.ts +93 -0
- package/dist/wagmi/Connector.d.ts.map +1 -0
- package/dist/wagmi/Connector.js +238 -0
- package/dist/wagmi/Connector.js.map +1 -0
- package/dist/wagmi/index.d.ts +3 -0
- package/dist/wagmi/index.d.ts.map +1 -0
- package/dist/wagmi/index.js +3 -0
- package/dist/wagmi/index.js.map +1 -0
- package/package.json +56 -2
- package/src/core/AccessKey.test.ts +257 -0
- package/src/core/AccessKey.ts +123 -0
- package/src/core/Account.test.ts +309 -0
- package/src/core/Account.ts +152 -0
- package/src/core/Adapter.ts +238 -0
- package/src/core/Ceremony.browser.test.ts +239 -0
- package/src/core/Ceremony.test.ts +151 -0
- package/src/core/Ceremony.ts +203 -0
- package/src/core/Client.ts +36 -0
- package/src/core/Dialog.browser.test.ts +309 -0
- package/src/core/Dialog.test-d.ts +19 -0
- package/src/core/Dialog.ts +442 -0
- package/src/core/Expiry.ts +34 -0
- package/src/core/Messenger.ts +206 -0
- package/src/core/Provider.browser.test.ts +774 -0
- package/src/core/Provider.connect.browser.test.ts +415 -0
- package/src/core/Provider.test-d.ts +53 -0
- package/src/core/Provider.test.ts +1566 -0
- package/src/core/Provider.ts +559 -0
- package/src/core/Remote.ts +262 -0
- package/src/core/Schema.test-d.ts +211 -0
- package/src/core/Schema.ts +143 -0
- package/src/core/Storage.ts +213 -0
- package/src/core/Store.test.ts +287 -0
- package/src/core/Store.ts +129 -0
- package/src/core/adapters/dangerous_secp256k1.ts +53 -0
- package/src/core/adapters/dialog.ts +379 -0
- package/src/core/adapters/local.test.ts +97 -0
- package/src/core/adapters/local.ts +277 -0
- package/src/core/adapters/webAuthn.ts +129 -0
- package/src/core/internal/withDedupe.test.ts +116 -0
- package/src/core/internal/withDedupe.ts +20 -0
- package/src/core/mppx.test.ts +83 -0
- package/src/core/zod/request.test.ts +121 -0
- package/src/core/zod/request.ts +70 -0
- package/src/core/zod/rpc.ts +374 -0
- package/src/core/zod/utils.test.ts +69 -0
- package/src/core/zod/utils.ts +40 -0
- package/src/index.ts +14 -0
- package/src/internal/types.ts +378 -0
- package/src/server/Handler.test.ts +1014 -0
- package/src/server/Handler.ts +605 -0
- package/src/server/Kv.ts +46 -0
- package/src/server/index.ts +2 -0
- package/src/server/internal/requestListener.ts +273 -0
- package/src/tsconfig.json +9 -0
- package/src/wagmi/Connector.ts +287 -0
- package/src/wagmi/index.ts +2 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
// Credit: https://github.com/mjackson/remix-the-web/blob/main/packages/node-fetch-server/src/lib/request-listener.ts
|
|
3
|
+
|
|
4
|
+
import type * as http from 'node:http'
|
|
5
|
+
import type * as http2 from 'node:http2'
|
|
6
|
+
|
|
7
|
+
export interface RequestListenerOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Overrides the host portion of the incoming request URL. By default the request URL host is
|
|
10
|
+
* derived from the HTTP `Host` header.
|
|
11
|
+
*
|
|
12
|
+
* For example, if you have a `$HOST` environment variable that contains the hostname of your
|
|
13
|
+
* server, you can use it to set the host of all incoming request URLs like so:
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* createRequestListener(handler, { host: process.env.HOST })
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
host?: string
|
|
20
|
+
/**
|
|
21
|
+
* An error handler that determines the response when the request handler throws an error. By
|
|
22
|
+
* default a 500 Internal Server Error response will be sent.
|
|
23
|
+
*/
|
|
24
|
+
onError?: ErrorHandler
|
|
25
|
+
/**
|
|
26
|
+
* Overrides the protocol of the incoming request URL. By default the request URL protocol is
|
|
27
|
+
* derived from the connection protocol. So e.g. when serving over HTTPS (using
|
|
28
|
+
* `https.createServer()`), the request URL will begin with `https:`.
|
|
29
|
+
*/
|
|
30
|
+
protocol?: string
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Wraps a fetch handler in a Node.js request listener that can be used with:
|
|
35
|
+
*
|
|
36
|
+
* - [`http.createServer()`](https://nodejs.org/api/http.html#httpcreateserveroptions-requestlistener)
|
|
37
|
+
* - [`https.createServer()`](https://nodejs.org/api/https.html#httpscreateserveroptions-requestlistener)
|
|
38
|
+
* - [`http2.createServer()`](https://nodejs.org/api/http2.html#http2createserveroptions-onrequesthandler)
|
|
39
|
+
* - [`http2.createSecureServer()`](https://nodejs.org/api/http2.html#http2createsecureserveroptions-onrequesthandler)
|
|
40
|
+
*
|
|
41
|
+
* Example:
|
|
42
|
+
*
|
|
43
|
+
* ```ts
|
|
44
|
+
* import * as http from 'node:http';
|
|
45
|
+
* import { createRequestListener } from '@mjackson/node-fetch-server';
|
|
46
|
+
*
|
|
47
|
+
* async function handler(request) {
|
|
48
|
+
* return new Response('Hello, world!');
|
|
49
|
+
* }
|
|
50
|
+
*
|
|
51
|
+
* let server = http.createServer(
|
|
52
|
+
* createRequestListener(handler)
|
|
53
|
+
* );
|
|
54
|
+
*
|
|
55
|
+
* server.listen(3000);
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @param handler The fetch handler to use for processing incoming requests.
|
|
59
|
+
* @param options Request listener options.
|
|
60
|
+
* @returns A Node.js request listener function.
|
|
61
|
+
*/
|
|
62
|
+
export function fromFetchHandler(
|
|
63
|
+
handler: FetchHandler,
|
|
64
|
+
options?: RequestListenerOptions,
|
|
65
|
+
): http.RequestListener {
|
|
66
|
+
const onError = options?.onError ?? defaultErrorHandler
|
|
67
|
+
|
|
68
|
+
return async (req, res) => {
|
|
69
|
+
const request = createRequest(req, res, options)
|
|
70
|
+
const client = {
|
|
71
|
+
address: req.socket.remoteAddress!,
|
|
72
|
+
family: req.socket.remoteFamily! as ClientAddress['family'],
|
|
73
|
+
port: req.socket.remotePort!,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let response: Response
|
|
77
|
+
try {
|
|
78
|
+
response = await handler(request, client)
|
|
79
|
+
} catch (error) {
|
|
80
|
+
try {
|
|
81
|
+
response = (await onError(error)) ?? internalServerError()
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error(`There was an error in the error handler: ${error}`)
|
|
84
|
+
response = internalServerError()
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
await sendResponse(res, response)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function defaultErrorHandler(error: unknown): Response {
|
|
93
|
+
console.error(error)
|
|
94
|
+
return internalServerError()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function internalServerError(): Response {
|
|
98
|
+
return new Response(
|
|
99
|
+
// "Internal Server Error"
|
|
100
|
+
new Uint8Array([
|
|
101
|
+
73, 110, 116, 101, 114, 110, 97, 108, 32, 83, 101, 114, 118, 101, 114, 32, 69, 114, 114, 111,
|
|
102
|
+
114,
|
|
103
|
+
]),
|
|
104
|
+
{
|
|
105
|
+
headers: {
|
|
106
|
+
'Content-Type': 'text/plain',
|
|
107
|
+
},
|
|
108
|
+
status: 500,
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export type RequestOptions = Omit<RequestListenerOptions, 'onError'>
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Creates a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object from
|
|
117
|
+
*
|
|
118
|
+
* - a [`http.IncomingMessage`](https://nodejs.org/api/http.html#class-httpincomingmessage)/[`http.ServerResponse`](https://nodejs.org/api/http.html#class-httpserverresponse) pair
|
|
119
|
+
* - a [`http2.Http2ServerRequest`](https://nodejs.org/api/http2.html#class-http2http2serverrequest)/[`http2.Http2ServerResponse`](https://nodejs.org/api/http2.html#class-http2http2serverresponse) pair
|
|
120
|
+
*
|
|
121
|
+
* @param req The incoming request object.
|
|
122
|
+
* @param res The server response object.
|
|
123
|
+
* @param options
|
|
124
|
+
* @returns A request object.
|
|
125
|
+
*/
|
|
126
|
+
export function createRequest(
|
|
127
|
+
req: http.IncomingMessage | http2.Http2ServerRequest,
|
|
128
|
+
res: http.ServerResponse | http2.Http2ServerResponse,
|
|
129
|
+
options?: RequestOptions,
|
|
130
|
+
): Request {
|
|
131
|
+
const controller = new AbortController()
|
|
132
|
+
res.on('close', () => {
|
|
133
|
+
controller.abort()
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
const method = req.method ?? 'GET'
|
|
137
|
+
const headers = createHeaders(req)
|
|
138
|
+
|
|
139
|
+
const protocol =
|
|
140
|
+
options?.protocol ?? ('encrypted' in req.socket && req.socket.encrypted ? 'https:' : 'http:')
|
|
141
|
+
const host = options?.host ?? headers.get('Host') ?? 'localhost'
|
|
142
|
+
const url = new URL(req.url!, `${protocol}//${host}`)
|
|
143
|
+
|
|
144
|
+
const init: RequestInit = { headers, method, signal: controller.signal }
|
|
145
|
+
|
|
146
|
+
if (method !== 'GET' && method !== 'HEAD') {
|
|
147
|
+
init.body = new ReadableStream({
|
|
148
|
+
start(controller) {
|
|
149
|
+
req.on('data', (chunk) => {
|
|
150
|
+
controller.enqueue(new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength))
|
|
151
|
+
})
|
|
152
|
+
req.on('end', () => {
|
|
153
|
+
controller.close()
|
|
154
|
+
})
|
|
155
|
+
},
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
// init.duplex = 'half' must be set when body is a ReadableStream, and Node follows the spec.
|
|
159
|
+
// However, this property is not defined in the TypeScript types for RequestInit, so we have
|
|
160
|
+
// to cast it here in order to set it without a type error.
|
|
161
|
+
// See https://fetch.spec.whatwg.org/#dom-requestinit-duplex
|
|
162
|
+
;(init as { duplex: 'half' }).duplex = 'half'
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return new Request(url, init)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Creates a [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) object from the headers in a Node.js
|
|
170
|
+
* [`http.IncomingMessage`](https://nodejs.org/api/http.html#class-httpincomingmessage)/[`http2.Http2ServerRequest`](https://nodejs.org/api/http2.html#class-http2http2serverrequest).
|
|
171
|
+
*
|
|
172
|
+
* @param req The incoming request object.
|
|
173
|
+
* @returns A headers object.
|
|
174
|
+
*/
|
|
175
|
+
export function createHeaders(req: http.IncomingMessage | http2.Http2ServerRequest): Headers {
|
|
176
|
+
const headers = new Headers()
|
|
177
|
+
|
|
178
|
+
const rawHeaders = req.rawHeaders
|
|
179
|
+
for (let i = 0; i < rawHeaders.length; i += 2) {
|
|
180
|
+
if (rawHeaders[i]?.startsWith(':')) continue
|
|
181
|
+
headers.append(rawHeaders[i]!, rawHeaders[i + 1]!)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return headers
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Sends a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) to the client using a Node.js
|
|
189
|
+
* [`http.ServerResponse`](https://nodejs.org/api/http.html#class-httpserverresponse)/[`http2.Http2ServerResponse`](https://nodejs.org/api/http2.html#class-http2http2serverresponse)
|
|
190
|
+
* object.
|
|
191
|
+
*
|
|
192
|
+
* @param res The server response object.
|
|
193
|
+
* @param response The response to send.
|
|
194
|
+
*/
|
|
195
|
+
export async function sendResponse(
|
|
196
|
+
res: http.ServerResponse | http2.Http2ServerResponse,
|
|
197
|
+
response: Response,
|
|
198
|
+
): Promise<void> {
|
|
199
|
+
// Iterate over response.headers so we are sure to send multiple Set-Cookie headers correctly.
|
|
200
|
+
// These would incorrectly be merged into a single header if we tried to use
|
|
201
|
+
// `Object.fromEntries(response.headers.entries())`.
|
|
202
|
+
const headers: Record<string, string | string[]> = {}
|
|
203
|
+
for (const [key, value] of response.headers as any) {
|
|
204
|
+
if (key in headers) {
|
|
205
|
+
if (Array.isArray(headers[key])) {
|
|
206
|
+
headers[key].push(value)
|
|
207
|
+
} else {
|
|
208
|
+
headers[key] = [headers[key] as string, value]
|
|
209
|
+
}
|
|
210
|
+
} else {
|
|
211
|
+
headers[key] = value
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
;(res as any).writeHead(response.status, headers)
|
|
216
|
+
|
|
217
|
+
if (response.body != null && res.req.method !== 'HEAD') {
|
|
218
|
+
for await (const chunk of readStream(response.body)) {
|
|
219
|
+
// @ts-expect-error - Node typings for http2 require a 2nd parameter to write but it's optional
|
|
220
|
+
res.write(chunk)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
res.end()
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export async function* readStream(stream: ReadableStream<Uint8Array>): AsyncIterable<Uint8Array> {
|
|
228
|
+
const reader = stream.getReader()
|
|
229
|
+
|
|
230
|
+
while (true) {
|
|
231
|
+
const { done, value } = await reader.read()
|
|
232
|
+
if (done) break
|
|
233
|
+
yield value
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export interface ClientAddress {
|
|
238
|
+
/**
|
|
239
|
+
* The IP address of the client that sent the request.
|
|
240
|
+
*
|
|
241
|
+
* [Node.js Reference](https://nodejs.org/api/net.html#socketremoteaddress)
|
|
242
|
+
*/
|
|
243
|
+
address: string
|
|
244
|
+
/**
|
|
245
|
+
* The family of the client IP address.
|
|
246
|
+
*
|
|
247
|
+
* [Node.js Reference](https://nodejs.org/api/net.html#socketremotefamily)
|
|
248
|
+
*/
|
|
249
|
+
family: 'IPv4' | 'IPv6'
|
|
250
|
+
/**
|
|
251
|
+
* The remote port of the client that sent the request.
|
|
252
|
+
*
|
|
253
|
+
* [Node.js Reference](https://nodejs.org/api/net.html#socketremoteport)
|
|
254
|
+
*/
|
|
255
|
+
port: number
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* A function that handles an error that occurred during request handling. May return a response to
|
|
260
|
+
* send to the client, or `undefined` to allow the server to send a default error response.
|
|
261
|
+
*
|
|
262
|
+
* [MDN `Response` Reference](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
|
263
|
+
*/
|
|
264
|
+
export type ErrorHandler = (error: unknown) => undefined | Response | Promise<undefined | Response>
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* A function that handles an incoming request and returns a response.
|
|
268
|
+
*
|
|
269
|
+
* [MDN `Request` Reference](https://developer.mozilla.org/en-US/docs/Web/API/Request)
|
|
270
|
+
*
|
|
271
|
+
* [MDN `Response` Reference](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
|
272
|
+
*/
|
|
273
|
+
export type FetchHandler = (request: Request, client: ClientAddress) => Response | Promise<Response>
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { ChainNotConfiguredError, type Connector, createConnector } from '@wagmi/core'
|
|
2
|
+
import {
|
|
3
|
+
type Address,
|
|
4
|
+
numberToHex,
|
|
5
|
+
type RpcError,
|
|
6
|
+
SwitchChainError,
|
|
7
|
+
UserRejectedRequestError,
|
|
8
|
+
} from 'viem'
|
|
9
|
+
import * as z from 'zod/mini'
|
|
10
|
+
|
|
11
|
+
import { dialog as core_dialog } from '../core/adapters/dialog.js'
|
|
12
|
+
import { webAuthn as webAuthn_adapter } from '../core/adapters/webAuthn.js'
|
|
13
|
+
import * as Provider from '../core/Provider.js'
|
|
14
|
+
import * as Rpc from '../core/zod/rpc.js'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates a wagmi connector backed by an accounts provider.
|
|
18
|
+
*/
|
|
19
|
+
export function setup(parameters: setup.Parameters = {} as setup.Parameters) {
|
|
20
|
+
type Properties = {
|
|
21
|
+
connect<withCapabilities extends boolean = false>(parameters?: {
|
|
22
|
+
capabilities?:
|
|
23
|
+
| NonNullable<z.output<typeof Rpc.wallet_connect.capabilities.request>>
|
|
24
|
+
| undefined
|
|
25
|
+
chainId?: number | undefined
|
|
26
|
+
isReconnecting?: boolean | undefined
|
|
27
|
+
withCapabilities?: withCapabilities | boolean | undefined
|
|
28
|
+
}): Promise<{
|
|
29
|
+
accounts: withCapabilities extends true
|
|
30
|
+
? readonly {
|
|
31
|
+
address: Address
|
|
32
|
+
capabilities: z.output<typeof Rpc.wallet_connect.capabilities.result>
|
|
33
|
+
}[]
|
|
34
|
+
: readonly Address[]
|
|
35
|
+
chainId: number
|
|
36
|
+
}>
|
|
37
|
+
}
|
|
38
|
+
return createConnector<Provider.Provider, Properties>((wagmiConfig) => {
|
|
39
|
+
const chains = wagmiConfig.chains
|
|
40
|
+
|
|
41
|
+
let provider: Provider.Provider | undefined
|
|
42
|
+
|
|
43
|
+
let accountsChanged: Connector['onAccountsChanged'] | undefined
|
|
44
|
+
let chainChanged: Connector['onChainChanged'] | undefined
|
|
45
|
+
let connect: Connector['onConnect'] | undefined
|
|
46
|
+
let disconnect: Connector['onDisconnect'] | undefined
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
async connect(params: Parameters<Properties['connect']>[0] = {}) {
|
|
50
|
+
const { isReconnecting, withCapabilities } = params
|
|
51
|
+
const capabilities = 'capabilities' in params ? params.capabilities : undefined
|
|
52
|
+
|
|
53
|
+
let accounts: readonly { address: Address; capabilities: Record<string, unknown> }[] = []
|
|
54
|
+
let currentChainId: number | undefined
|
|
55
|
+
|
|
56
|
+
if (isReconnecting)
|
|
57
|
+
accounts = await this.getAccounts()
|
|
58
|
+
.then((accounts) => accounts.map((address) => ({ address, capabilities: {} })))
|
|
59
|
+
.catch(() => [])
|
|
60
|
+
|
|
61
|
+
const provider = (await this.getProvider()) as Provider.create.ReturnType
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
if (!accounts?.length && !isReconnecting) {
|
|
65
|
+
const res = await provider.request({
|
|
66
|
+
method: 'wallet_connect',
|
|
67
|
+
params: [
|
|
68
|
+
capabilities
|
|
69
|
+
? {
|
|
70
|
+
capabilities: z.encode(Rpc.wallet_connect.capabilities.request, capabilities),
|
|
71
|
+
}
|
|
72
|
+
: {},
|
|
73
|
+
] as never,
|
|
74
|
+
})
|
|
75
|
+
accounts = res.accounts
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
currentChainId ??= await this.getChainId()
|
|
79
|
+
if (!currentChainId) throw new ChainNotConfiguredError()
|
|
80
|
+
|
|
81
|
+
if (connect) {
|
|
82
|
+
provider.removeListener('connect', connect)
|
|
83
|
+
connect = undefined
|
|
84
|
+
}
|
|
85
|
+
if (!accountsChanged) {
|
|
86
|
+
accountsChanged = this.onAccountsChanged.bind(this)
|
|
87
|
+
provider.on('accountsChanged', accountsChanged as never)
|
|
88
|
+
}
|
|
89
|
+
if (!chainChanged) {
|
|
90
|
+
chainChanged = this.onChainChanged.bind(this)
|
|
91
|
+
provider.on('chainChanged', chainChanged!)
|
|
92
|
+
}
|
|
93
|
+
if (!disconnect) {
|
|
94
|
+
disconnect = this.onDisconnect.bind(this)
|
|
95
|
+
provider.on('disconnect', disconnect!)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
accounts: (withCapabilities ? accounts : accounts.map((a) => a.address)) as never,
|
|
100
|
+
chainId: currentChainId,
|
|
101
|
+
}
|
|
102
|
+
} catch (err) {
|
|
103
|
+
const error = err as RpcError
|
|
104
|
+
if (error.code === UserRejectedRequestError.code)
|
|
105
|
+
throw new UserRejectedRequestError(error)
|
|
106
|
+
throw error
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
async disconnect() {
|
|
110
|
+
const provider = (await this.getProvider()) as Provider.create.ReturnType
|
|
111
|
+
|
|
112
|
+
if (chainChanged) {
|
|
113
|
+
provider.removeListener('chainChanged', chainChanged)
|
|
114
|
+
chainChanged = undefined
|
|
115
|
+
}
|
|
116
|
+
if (disconnect) {
|
|
117
|
+
provider.removeListener('disconnect', disconnect)
|
|
118
|
+
disconnect = undefined
|
|
119
|
+
}
|
|
120
|
+
if (!connect) {
|
|
121
|
+
connect = this.onConnect?.bind(this)
|
|
122
|
+
if (connect) provider.on('connect', connect as never)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
await provider.request({ method: 'wallet_disconnect' })
|
|
126
|
+
},
|
|
127
|
+
async getAccounts() {
|
|
128
|
+
const provider = (await this.getProvider()) as Provider.create.ReturnType
|
|
129
|
+
return provider.request({ method: 'eth_accounts' })
|
|
130
|
+
},
|
|
131
|
+
async getChainId() {
|
|
132
|
+
const provider = (await this.getProvider()) as Provider.create.ReturnType
|
|
133
|
+
const hexChainId = await provider.request({ method: 'eth_chainId' })
|
|
134
|
+
return Number(hexChainId)
|
|
135
|
+
},
|
|
136
|
+
async getProvider() {
|
|
137
|
+
provider ??= Provider.create({
|
|
138
|
+
...parameters,
|
|
139
|
+
chains: chains as never,
|
|
140
|
+
})
|
|
141
|
+
return provider as never
|
|
142
|
+
},
|
|
143
|
+
icon: parameters.adapter?.icon,
|
|
144
|
+
id: parameters.adapter?.rdns ?? 'com.example',
|
|
145
|
+
async isAuthorized() {
|
|
146
|
+
try {
|
|
147
|
+
const accounts = await this.getAccounts()
|
|
148
|
+
return !!accounts.length
|
|
149
|
+
} catch {
|
|
150
|
+
return false
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
name: parameters.adapter?.name ?? 'Accounts',
|
|
154
|
+
async onAccountsChanged(accounts) {
|
|
155
|
+
wagmiConfig.emitter.emit('change', {
|
|
156
|
+
accounts: accounts as readonly Address[],
|
|
157
|
+
})
|
|
158
|
+
},
|
|
159
|
+
onChainChanged(chain) {
|
|
160
|
+
const chainId = Number(chain)
|
|
161
|
+
wagmiConfig.emitter.emit('change', { chainId })
|
|
162
|
+
},
|
|
163
|
+
async onConnect(connectInfo) {
|
|
164
|
+
const accounts = await this.getAccounts()
|
|
165
|
+
if (accounts.length === 0) return
|
|
166
|
+
|
|
167
|
+
const chainId = Number(connectInfo.chainId)
|
|
168
|
+
wagmiConfig.emitter.emit('connect', { accounts, chainId })
|
|
169
|
+
|
|
170
|
+
const provider = (await this.getProvider()) as Provider.create.ReturnType
|
|
171
|
+
if (connect) {
|
|
172
|
+
provider.removeListener('connect', connect)
|
|
173
|
+
connect = undefined
|
|
174
|
+
}
|
|
175
|
+
if (!accountsChanged) {
|
|
176
|
+
accountsChanged = this.onAccountsChanged.bind(this)
|
|
177
|
+
provider.on('accountsChanged', accountsChanged as never)
|
|
178
|
+
}
|
|
179
|
+
if (!chainChanged) {
|
|
180
|
+
chainChanged = this.onChainChanged.bind(this)
|
|
181
|
+
provider.on('chainChanged', chainChanged!)
|
|
182
|
+
}
|
|
183
|
+
if (!disconnect) {
|
|
184
|
+
disconnect = this.onDisconnect.bind(this)
|
|
185
|
+
provider.on('disconnect', disconnect!)
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
async onDisconnect(_error) {
|
|
189
|
+
const provider = (await this.getProvider()) as Provider.create.ReturnType
|
|
190
|
+
|
|
191
|
+
wagmiConfig.emitter.emit('disconnect')
|
|
192
|
+
|
|
193
|
+
if (chainChanged) {
|
|
194
|
+
provider.removeListener('chainChanged', chainChanged)
|
|
195
|
+
chainChanged = undefined
|
|
196
|
+
}
|
|
197
|
+
if (disconnect) {
|
|
198
|
+
provider.removeListener('disconnect', disconnect)
|
|
199
|
+
disconnect = undefined
|
|
200
|
+
}
|
|
201
|
+
if (!connect) {
|
|
202
|
+
connect = this.onConnect?.bind(this)
|
|
203
|
+
if (connect) provider.on('connect', connect as never)
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
async setup() {
|
|
207
|
+
if (!connect) {
|
|
208
|
+
const provider = (await this.getProvider()) as Provider.create.ReturnType
|
|
209
|
+
connect = this.onConnect?.bind(this)
|
|
210
|
+
if (connect) provider.on('connect', connect as never)
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
async switchChain({ chainId }) {
|
|
214
|
+
const chain = chains.find((x) => x.id === chainId)
|
|
215
|
+
if (!chain) throw new SwitchChainError(new ChainNotConfiguredError())
|
|
216
|
+
|
|
217
|
+
const provider = (await this.getProvider()) as Provider.create.ReturnType
|
|
218
|
+
await provider.request({
|
|
219
|
+
method: 'wallet_switchEthereumChain',
|
|
220
|
+
params: [{ chainId: numberToHex(chainId) }],
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
return chain
|
|
224
|
+
},
|
|
225
|
+
type: 'injected',
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export declare namespace setup {
|
|
231
|
+
type Parameters = Provider.create.Options
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Creates a wagmi connector backed by a WebAuthn adapter.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```ts
|
|
239
|
+
* import { createConfig, http } from 'wagmi'
|
|
240
|
+
* import { tempoModerato } from 'wagmi/chains'
|
|
241
|
+
* import { webAuthn } from 'accounts/wagmi'
|
|
242
|
+
*
|
|
243
|
+
* const config = createConfig({
|
|
244
|
+
* chains: [tempoModerato],
|
|
245
|
+
* connectors: [webAuthn()],
|
|
246
|
+
* transports: { [tempoModerato.id]: http() },
|
|
247
|
+
* })
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
export function webAuthn(options: webAuthn.Options = {}) {
|
|
251
|
+
const { ceremony, icon, name, rdns, ...rest } = options
|
|
252
|
+
return setup({
|
|
253
|
+
...rest,
|
|
254
|
+
adapter: webAuthn_adapter({ ceremony, icon, name, rdns }),
|
|
255
|
+
})
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export declare namespace webAuthn {
|
|
259
|
+
type Options = webAuthn_adapter.Options & Omit<setup.Parameters, 'adapter'>
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Creates a wagmi connector backed by a dialog adapter.
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* ```ts
|
|
267
|
+
* import { createConfig, http } from 'wagmi'
|
|
268
|
+
* import { tempoModerato } from 'wagmi/chains'
|
|
269
|
+
* import { dialog } from 'accounts/wagmi'
|
|
270
|
+
*
|
|
271
|
+
* const config = createConfig({
|
|
272
|
+
* chains: [tempoModerato],
|
|
273
|
+
* connectors: [dialog()],
|
|
274
|
+
* transports: { [tempoModerato.id]: http() },
|
|
275
|
+
* })
|
|
276
|
+
* ```
|
|
277
|
+
*/
|
|
278
|
+
export function dialog(options: dialog.Options = {}) {
|
|
279
|
+
const { dialog: dialogOption, host, icon, name, rdns } = options
|
|
280
|
+
return setup({
|
|
281
|
+
adapter: core_dialog({ dialog: dialogOption, host, icon, name, rdns }),
|
|
282
|
+
})
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export declare namespace dialog {
|
|
286
|
+
type Options = core_dialog.Options & Omit<setup.Parameters, 'adapter'>
|
|
287
|
+
}
|