@fourt/sdk 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/README.md +86 -0
- package/dist/index.cjs +625 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +278 -0
- package/dist/index.d.ts +278 -0
- package/dist/index.js +604 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.cjs +19 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +13 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# @fourt/sdk
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
The Fourt Software Development Kit (SDK) is a TypeScript library that allows you to interact with the Fourt.io services and use them in your projects.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pnpm add @fourt/sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npm install @fourt/sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
yarn add @fourt/sdk
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
To initialize the SDK, you will need to pass your API key to the one of the **Signer** constructors. You will also be asked to provide additional options for authentication methods. As of now, the SDK only supports authentication through passkeys (see [Web Authentication](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API)), and thus only `FourtWebSigner` is available.
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { FourtWebSigner } from '@fourt/sdk'
|
|
27
|
+
|
|
28
|
+
const fourtWebSigner = new FourtWebSigner({
|
|
29
|
+
auth: {
|
|
30
|
+
webauthn: {
|
|
31
|
+
rpId: 'localhost',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
configuration: {
|
|
35
|
+
apiKey: '<YOUR_API_KEY>',
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Modules
|
|
41
|
+
|
|
42
|
+
The SDK is divided into several modules, each one with a specific purpose:
|
|
43
|
+
|
|
44
|
+
- `AuthModule`: A module that allows you to authenticate users with the Fourt.io services;
|
|
45
|
+
- `UserModule`: A module that allows you to get information about the authenticated user;
|
|
46
|
+
- `ViemModule`: A module that offers utilities to interact with the Ethereum ecosystem using [Viem](https://viem.sh/).
|
|
47
|
+
|
|
48
|
+
Each module can be accessed through the `auth`, `user` and `viem` properties on the Signer instance, e.g.
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
await fourtWebSigner.auth.passkeys.signIn({
|
|
52
|
+
email,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// Will print a `User` object, as defined in `@fourt/sdk/types`.
|
|
56
|
+
console.log(fourtWebSigner.user.info)
|
|
57
|
+
|
|
58
|
+
// Use the Viem module to interact with the Ethereum ecosystem
|
|
59
|
+
const localAccount = await fourtWebSigner.viem.toLocalAccount()
|
|
60
|
+
|
|
61
|
+
// Sign a message with the local account
|
|
62
|
+
const signature = await localAccount.signMessage({ message })
|
|
63
|
+
console.log(signature)
|
|
64
|
+
|
|
65
|
+
// Create a smart account instance
|
|
66
|
+
import { createPublicClient, http } from 'viem'
|
|
67
|
+
import { polygonAmoy } from 'viem/chains'
|
|
68
|
+
|
|
69
|
+
// You will need to create a public client to interact with the Ethereum ecosystem
|
|
70
|
+
const publicClient = createPublicClient({
|
|
71
|
+
chain: polygonAmoy,
|
|
72
|
+
transport: http('YOUR_RPC_URL'),
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
const smartAccount = await fourtWebSigner.viem.toSmartAccount({
|
|
76
|
+
owner: localAccount,
|
|
77
|
+
client,
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
// Take some action based on the smart account state
|
|
81
|
+
if (smartAccount.isDeployed) {
|
|
82
|
+
console.log('Smart account is deployed')
|
|
83
|
+
} else {
|
|
84
|
+
console.log('Smart account is not deployed. Airdropping tokens...')
|
|
85
|
+
}
|
|
86
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
FourtWebSigner: () => FourtWebSigner
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(src_exports);
|
|
26
|
+
|
|
27
|
+
// src/signer/web.ts
|
|
28
|
+
var import_webauthn_stamper = require("@turnkey/webauthn-stamper");
|
|
29
|
+
|
|
30
|
+
// src/signer/index.ts
|
|
31
|
+
var import_http = require("@turnkey/http");
|
|
32
|
+
|
|
33
|
+
// src/errors/SDKError.ts
|
|
34
|
+
var SDKError = class extends Error {
|
|
35
|
+
_props;
|
|
36
|
+
constructor(message, props) {
|
|
37
|
+
super(message);
|
|
38
|
+
this._props = props;
|
|
39
|
+
}
|
|
40
|
+
get message() {
|
|
41
|
+
return this._props.message;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// src/errors/UnauthorizedError.ts
|
|
46
|
+
var UnauthorizedError = class _UnauthorizedError extends SDKError {
|
|
47
|
+
constructor(props) {
|
|
48
|
+
super(_UnauthorizedError.name, props);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/errors/NotFoundError.ts
|
|
53
|
+
var NotFoundError = class _NotFoundError extends SDKError {
|
|
54
|
+
constructor(props) {
|
|
55
|
+
super(_NotFoundError.name, props);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/errors/GenericError.ts
|
|
60
|
+
var GenericError = class _GenericError extends SDKError {
|
|
61
|
+
constructor(props) {
|
|
62
|
+
super(_GenericError.name, props);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// src/errors/UnauthenticatedError.ts
|
|
67
|
+
var UnauthenticatedError = class _UnauthenticatedError extends SDKError {
|
|
68
|
+
constructor(props) {
|
|
69
|
+
super(_UnauthenticatedError.name, props);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// src/errors/BadRequestError.ts
|
|
74
|
+
var BadRequestError = class _BadRequestError extends SDKError {
|
|
75
|
+
constructor(props) {
|
|
76
|
+
super(_BadRequestError.name, props);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// src/session/index.ts
|
|
81
|
+
var import_zustand = require("zustand");
|
|
82
|
+
var import_middleware = require("zustand/middleware");
|
|
83
|
+
var SessionStore = class {
|
|
84
|
+
_store;
|
|
85
|
+
/**
|
|
86
|
+
* Initializes a new instance of the `SessionStore` class by creating a new `zustand`store with the initial state.
|
|
87
|
+
*/
|
|
88
|
+
constructor() {
|
|
89
|
+
this._store = (0, import_zustand.createStore)()(
|
|
90
|
+
(0, import_middleware.persist)(this._getInitialState, {
|
|
91
|
+
name: "fourt.io-signer-session",
|
|
92
|
+
storage: (0, import_middleware.createJSONStorage)(() => localStorage)
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Gets the token from the session state.
|
|
98
|
+
*
|
|
99
|
+
* @returns {string | undefined} the token.
|
|
100
|
+
*/
|
|
101
|
+
get token() {
|
|
102
|
+
return this._store.getState().token;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Sets the token in the session state.
|
|
106
|
+
*
|
|
107
|
+
* @param {string} token the token to set.
|
|
108
|
+
*/
|
|
109
|
+
set token(token) {
|
|
110
|
+
this._store.setState({ token });
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Gets the user from the session state.
|
|
114
|
+
*
|
|
115
|
+
* @returns {User | undefined} the user.
|
|
116
|
+
*/
|
|
117
|
+
get user() {
|
|
118
|
+
return this._store.getState().user;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Sets the user in the session state.
|
|
122
|
+
*
|
|
123
|
+
* @param {User} user the user to set.
|
|
124
|
+
*/
|
|
125
|
+
set user(user) {
|
|
126
|
+
this._store.setState({ ...this._store.getState(), user });
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Clears the user from the session state.
|
|
130
|
+
*/
|
|
131
|
+
clearUser() {
|
|
132
|
+
this._store.setState({ ...this._store.getState(), user: void 0 });
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Clears the token from the session state.
|
|
136
|
+
*/
|
|
137
|
+
clearToken() {
|
|
138
|
+
this._store.setState({ ...this._store.getState(), token: void 0 });
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Clears the token and user from the session state.
|
|
142
|
+
*/
|
|
143
|
+
clearAll() {
|
|
144
|
+
this.clearToken();
|
|
145
|
+
this.clearUser();
|
|
146
|
+
}
|
|
147
|
+
_getInitialState() {
|
|
148
|
+
return {
|
|
149
|
+
user: void 0,
|
|
150
|
+
token: void 0
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// src/types/Routes.ts
|
|
156
|
+
var ROUTE_METHOD_MAP = {
|
|
157
|
+
"/v1/signup": "POST",
|
|
158
|
+
"/v1/lookup": "POST",
|
|
159
|
+
"/v1/signin": "POST",
|
|
160
|
+
"/v1/sign": "POST"
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// src/signer/index.ts
|
|
164
|
+
var import_jwt_decode = require("jwt-decode");
|
|
165
|
+
var import_date_fns = require("date-fns");
|
|
166
|
+
var SignerClient = class {
|
|
167
|
+
_turnkeyClient;
|
|
168
|
+
_configuration;
|
|
169
|
+
_sessionStore;
|
|
170
|
+
_user;
|
|
171
|
+
constructor({
|
|
172
|
+
stamper,
|
|
173
|
+
configuration: { apiUrl, ...requiredConfiguration }
|
|
174
|
+
}) {
|
|
175
|
+
this._turnkeyClient = new import_http.TurnkeyClient(
|
|
176
|
+
{ baseUrl: "https://api.turnkey.com" },
|
|
177
|
+
stamper
|
|
178
|
+
);
|
|
179
|
+
this._configuration = {
|
|
180
|
+
...requiredConfiguration,
|
|
181
|
+
apiUrl: apiUrl ?? "https://auth.dev.api.fourt.io"
|
|
182
|
+
};
|
|
183
|
+
this._sessionStore = new SessionStore();
|
|
184
|
+
}
|
|
185
|
+
get user() {
|
|
186
|
+
if (this._user) return this._user;
|
|
187
|
+
if (!this.sessionStore.token) {
|
|
188
|
+
this.sessionStore.clearAll();
|
|
189
|
+
return void 0;
|
|
190
|
+
}
|
|
191
|
+
const decodedToken = (0, import_jwt_decode.jwtDecode)(this.sessionStore.token);
|
|
192
|
+
if (decodedToken.exp && (0, import_date_fns.isPast)(new Date((0, import_date_fns.secondsToMilliseconds)(decodedToken.exp)))) {
|
|
193
|
+
this.sessionStore.clearAll();
|
|
194
|
+
return void 0;
|
|
195
|
+
}
|
|
196
|
+
if (this.sessionStore.user) this._user = this.sessionStore.user;
|
|
197
|
+
return this._user;
|
|
198
|
+
}
|
|
199
|
+
set user(value) {
|
|
200
|
+
this._user = value;
|
|
201
|
+
}
|
|
202
|
+
set stamper(stamper) {
|
|
203
|
+
this._turnkeyClient.stamper = stamper;
|
|
204
|
+
}
|
|
205
|
+
get stamper() {
|
|
206
|
+
return this._turnkeyClient.stamper;
|
|
207
|
+
}
|
|
208
|
+
get sessionStore() {
|
|
209
|
+
return this._sessionStore;
|
|
210
|
+
}
|
|
211
|
+
async signRawMessage(msg) {
|
|
212
|
+
if (!this._user) {
|
|
213
|
+
throw new UnauthorizedError({
|
|
214
|
+
message: "SignerClient must be authenticated to sign a message"
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
const stampedRequest = await this._turnkeyClient.stampSignRawPayload({
|
|
218
|
+
organizationId: this._user.subOrgId,
|
|
219
|
+
type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2",
|
|
220
|
+
timestampMs: Date.now().toString(),
|
|
221
|
+
parameters: {
|
|
222
|
+
encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
|
|
223
|
+
hashFunction: "HASH_FUNCTION_NO_OP",
|
|
224
|
+
payload: msg,
|
|
225
|
+
signWith: this._user.walletAddress
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
const { signature } = await this.request("/v1/sign", {
|
|
229
|
+
stampedRequest
|
|
230
|
+
});
|
|
231
|
+
return signature;
|
|
232
|
+
}
|
|
233
|
+
async lookUpUser(email) {
|
|
234
|
+
try {
|
|
235
|
+
const { subOrgId } = await this.request("/v1/lookup", { email });
|
|
236
|
+
return subOrgId;
|
|
237
|
+
} catch (error) {
|
|
238
|
+
if (!(error instanceof SDKError)) throw error;
|
|
239
|
+
const sdkError = error;
|
|
240
|
+
switch (sdkError.constructor.name) {
|
|
241
|
+
case NotFoundError.name: {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
default: {
|
|
245
|
+
throw sdkError;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
async whoAmI(subOrgId) {
|
|
251
|
+
const orgId = subOrgId || this._user?.subOrgId;
|
|
252
|
+
if (!orgId) throw new BadRequestError({ message: "No orgId provided" });
|
|
253
|
+
const stampedRequest = await this._turnkeyClient.stampGetWhoami({
|
|
254
|
+
organizationId: orgId
|
|
255
|
+
});
|
|
256
|
+
const { user, token } = await this.request("/v1/signin", {
|
|
257
|
+
stampedRequest
|
|
258
|
+
});
|
|
259
|
+
const credentialId = (() => {
|
|
260
|
+
try {
|
|
261
|
+
return JSON.parse(stampedRequest?.stamp.stampHeaderValue).credentialId;
|
|
262
|
+
} catch (e) {
|
|
263
|
+
return void 0;
|
|
264
|
+
}
|
|
265
|
+
})();
|
|
266
|
+
this._user = {
|
|
267
|
+
...user,
|
|
268
|
+
credentialId
|
|
269
|
+
};
|
|
270
|
+
this.sessionStore.user = this.user;
|
|
271
|
+
this.sessionStore.token = token;
|
|
272
|
+
}
|
|
273
|
+
async request(route, body) {
|
|
274
|
+
const url = new URL(`${route}`, this._configuration.apiUrl);
|
|
275
|
+
const token = this.sessionStore.token;
|
|
276
|
+
const headers = {
|
|
277
|
+
"Content-Type": "application/json",
|
|
278
|
+
"X-FOURT-KEY": this._configuration.apiKey
|
|
279
|
+
};
|
|
280
|
+
if (token) {
|
|
281
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
282
|
+
}
|
|
283
|
+
const response = await fetch(url, {
|
|
284
|
+
method: ROUTE_METHOD_MAP[route],
|
|
285
|
+
body: JSON.stringify(body),
|
|
286
|
+
headers,
|
|
287
|
+
credentials: "include"
|
|
288
|
+
});
|
|
289
|
+
const { data, error } = await response.json();
|
|
290
|
+
if (error) {
|
|
291
|
+
switch (error.kind) {
|
|
292
|
+
case "UnauthorizedError": {
|
|
293
|
+
this.user = void 0;
|
|
294
|
+
this.sessionStore.clearAll();
|
|
295
|
+
throw new UnauthorizedError({ message: error.message });
|
|
296
|
+
}
|
|
297
|
+
case "NotFoundError": {
|
|
298
|
+
throw new NotFoundError({ message: error.message });
|
|
299
|
+
}
|
|
300
|
+
case "BadRequestError": {
|
|
301
|
+
throw new BadRequestError({ message: error.message });
|
|
302
|
+
}
|
|
303
|
+
default: {
|
|
304
|
+
throw new GenericError({ message: error.message });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return { ...data };
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
// src/lib/base64.ts
|
|
313
|
+
var import_buffer = require("buffer");
|
|
314
|
+
var LibBase64 = class {
|
|
315
|
+
static fromBuffer(buffer) {
|
|
316
|
+
return import_buffer.Buffer.from(buffer).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
317
|
+
}
|
|
318
|
+
static toBuffer(base64) {
|
|
319
|
+
return import_buffer.Buffer.from(base64, "base64");
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
// src/lib/bytes.ts
|
|
324
|
+
var LibBytes = class {
|
|
325
|
+
static generateRandomBuffer = () => {
|
|
326
|
+
const arr = new Uint8Array(32);
|
|
327
|
+
crypto.getRandomValues(arr);
|
|
328
|
+
return arr.buffer;
|
|
329
|
+
};
|
|
330
|
+
static takeBytes = (bytes, params = {}) => {
|
|
331
|
+
const { offset, count } = params;
|
|
332
|
+
const start = (offset ? offset * 2 : 0) + 2;
|
|
333
|
+
const end = count ? start + count * 2 : void 0;
|
|
334
|
+
return `0x${bytes.slice(start, end)}`;
|
|
335
|
+
};
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// src/signer/web.ts
|
|
339
|
+
var import_http2 = require("@turnkey/http");
|
|
340
|
+
var WebSignerClient = class extends SignerClient {
|
|
341
|
+
_stampers;
|
|
342
|
+
/**
|
|
343
|
+
* Initializes a new instance of the `WebSignerClient` class.
|
|
344
|
+
*
|
|
345
|
+
* @param {WebSignerClientConstructorParams} params params for the constructor
|
|
346
|
+
*/
|
|
347
|
+
constructor({ configuration, webauthn }) {
|
|
348
|
+
const webauthnStamper = new import_webauthn_stamper.WebauthnStamper({ rpId: webauthn.rpId });
|
|
349
|
+
super({
|
|
350
|
+
stamper: webauthnStamper,
|
|
351
|
+
configuration
|
|
352
|
+
});
|
|
353
|
+
this._stampers = {
|
|
354
|
+
webauthn: webauthnStamper
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Signs in a user with webauthn.
|
|
359
|
+
*
|
|
360
|
+
* @param {WebauthnSignInParams} params params for the sign in
|
|
361
|
+
*/
|
|
362
|
+
async webauthnSignIn({ email }) {
|
|
363
|
+
const existingUserSubOrgId = await this.lookUpUser(email);
|
|
364
|
+
if (!existingUserSubOrgId) {
|
|
365
|
+
await this._createAccount({ method: "webauthn", email });
|
|
366
|
+
} else {
|
|
367
|
+
await this.whoAmI(existingUserSubOrgId);
|
|
368
|
+
if (!this.user || !this.user.credentialId) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
this.stamper = this._stampers.webauthn;
|
|
372
|
+
this._stampers.webauthn.allowCredentials = [
|
|
373
|
+
{
|
|
374
|
+
id: LibBase64.toBuffer(this.user.credentialId),
|
|
375
|
+
type: "public-key",
|
|
376
|
+
transports: ["internal", "usb"]
|
|
377
|
+
}
|
|
378
|
+
];
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
async _createAccount(params) {
|
|
382
|
+
const { challenge, attestation } = await this._webauthnGenerateAttestation(
|
|
383
|
+
params.email
|
|
384
|
+
);
|
|
385
|
+
const {
|
|
386
|
+
token,
|
|
387
|
+
user: { id, email, subOrgId, walletAddress, salt, smartAccountAddress }
|
|
388
|
+
} = await this.request("/v1/signup", {
|
|
389
|
+
passkey: {
|
|
390
|
+
challenge: LibBase64.fromBuffer(challenge),
|
|
391
|
+
attestation
|
|
392
|
+
},
|
|
393
|
+
email: params.email
|
|
394
|
+
});
|
|
395
|
+
this.user = {
|
|
396
|
+
id,
|
|
397
|
+
email,
|
|
398
|
+
subOrgId,
|
|
399
|
+
walletAddress,
|
|
400
|
+
salt,
|
|
401
|
+
smartAccountAddress,
|
|
402
|
+
credentialId: attestation.credentialId
|
|
403
|
+
};
|
|
404
|
+
this._sessionStore.token = token;
|
|
405
|
+
}
|
|
406
|
+
async _webauthnGenerateAttestation(email) {
|
|
407
|
+
const challenge = LibBytes.generateRandomBuffer();
|
|
408
|
+
const authenticatorUserId = LibBytes.generateRandomBuffer();
|
|
409
|
+
const attestation = await (0, import_http2.getWebAuthnAttestation)({
|
|
410
|
+
publicKey: {
|
|
411
|
+
authenticatorSelection: {
|
|
412
|
+
residentKey: "preferred",
|
|
413
|
+
requireResidentKey: false,
|
|
414
|
+
userVerification: "preferred"
|
|
415
|
+
},
|
|
416
|
+
challenge,
|
|
417
|
+
rp: {
|
|
418
|
+
id: window.location.hostname,
|
|
419
|
+
name: window.location.hostname
|
|
420
|
+
},
|
|
421
|
+
pubKeyCredParams: [
|
|
422
|
+
{
|
|
423
|
+
type: "public-key",
|
|
424
|
+
alg: -7
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
type: "public-key",
|
|
428
|
+
alg: -257
|
|
429
|
+
}
|
|
430
|
+
],
|
|
431
|
+
user: {
|
|
432
|
+
id: authenticatorUserId,
|
|
433
|
+
name: email,
|
|
434
|
+
displayName: email
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
return { challenge, attestation, authenticatorUserId };
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
// src/third-party/viem.ts
|
|
443
|
+
var import_viem = require("viem");
|
|
444
|
+
var import_accounts = require("viem/accounts");
|
|
445
|
+
var import_accounts2 = require("permissionless/accounts");
|
|
446
|
+
var import_account_abstraction = require("viem/account-abstraction");
|
|
447
|
+
var ViemModule = class {
|
|
448
|
+
constructor(_signerClient) {
|
|
449
|
+
this._signerClient = _signerClient;
|
|
450
|
+
}
|
|
451
|
+
async toLocalAccount() {
|
|
452
|
+
const user = this._signerClient.user;
|
|
453
|
+
if (!user) {
|
|
454
|
+
throw new UnauthenticatedError({ message: "Signer not authenticated" });
|
|
455
|
+
}
|
|
456
|
+
return (0, import_accounts.toAccount)({
|
|
457
|
+
address: user.walletAddress,
|
|
458
|
+
signMessage: (msg) => this.signMessage(msg.message),
|
|
459
|
+
signTypedData: (typedDataDefinition) => this.signTypedData(typedDataDefinition),
|
|
460
|
+
signTransaction: this.signTransaction
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
async toSmartAccount({
|
|
464
|
+
client,
|
|
465
|
+
owner
|
|
466
|
+
}) {
|
|
467
|
+
const user = this._signerClient.user;
|
|
468
|
+
if (!user) {
|
|
469
|
+
throw new UnauthenticatedError({ message: "Signer not authenticated" });
|
|
470
|
+
}
|
|
471
|
+
return (0, import_accounts2.toLightSmartAccount)({
|
|
472
|
+
client,
|
|
473
|
+
owner,
|
|
474
|
+
version: "2.0.0",
|
|
475
|
+
entryPoint: {
|
|
476
|
+
address: import_account_abstraction.entryPoint07Address,
|
|
477
|
+
version: "0.7"
|
|
478
|
+
},
|
|
479
|
+
address: user.smartAccountAddress,
|
|
480
|
+
index: (0, import_viem.hexToBigInt)(user.salt)
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
async signMessage(msg) {
|
|
484
|
+
const messageHash = (0, import_viem.hashMessage)(msg);
|
|
485
|
+
const result = await this._signerClient.signRawMessage(messageHash);
|
|
486
|
+
return result;
|
|
487
|
+
}
|
|
488
|
+
async signTypedData(params) {
|
|
489
|
+
const messageHash = (0, import_viem.hashTypedData)(params);
|
|
490
|
+
return this._signerClient.signRawMessage(messageHash);
|
|
491
|
+
}
|
|
492
|
+
async signTransaction(transaction, options) {
|
|
493
|
+
const serializeFn = options?.serializer ?? import_viem.serializeTransaction;
|
|
494
|
+
const serializedTx = serializeFn(transaction);
|
|
495
|
+
const signatureHex = await this._signerClient.signRawMessage(
|
|
496
|
+
(0, import_viem.keccak256)(serializedTx)
|
|
497
|
+
);
|
|
498
|
+
const signature = {
|
|
499
|
+
r: LibBytes.takeBytes(signatureHex, { count: 32 }),
|
|
500
|
+
s: LibBytes.takeBytes(signatureHex, { count: 32, offset: 32 }),
|
|
501
|
+
v: BigInt(LibBytes.takeBytes(signatureHex, { count: 1, offset: 64 }))
|
|
502
|
+
};
|
|
503
|
+
return serializeFn(transaction, signature);
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
// src/modules/auth/passkeys.ts
|
|
508
|
+
var PasskeysModule = class {
|
|
509
|
+
constructor(_webSignerClient) {
|
|
510
|
+
this._webSignerClient = _webSignerClient;
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Signs in a user using Passkeys.
|
|
514
|
+
*
|
|
515
|
+
* @param params {WebauthnSignInParams} params for the sign-in process.
|
|
516
|
+
* @returns {Promise<void>} promise that resolves to the result of the sign-in process.
|
|
517
|
+
*/
|
|
518
|
+
async signIn(params) {
|
|
519
|
+
return this._webSignerClient.webauthnSignIn(params);
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
// src/modules/auth/index.ts
|
|
524
|
+
var AuthModule = class {
|
|
525
|
+
/**
|
|
526
|
+
* Initializes a new instance of the `AuthModule` class.
|
|
527
|
+
*
|
|
528
|
+
* @param {WebSignerClient} _webSignerClient underlying WebSigner client instance.
|
|
529
|
+
*/
|
|
530
|
+
constructor(_webSignerClient) {
|
|
531
|
+
this._webSignerClient = _webSignerClient;
|
|
532
|
+
this._passkeys = new PasskeysModule(this._webSignerClient);
|
|
533
|
+
}
|
|
534
|
+
_passkeys;
|
|
535
|
+
/**
|
|
536
|
+
* A module for interacting with the Passkeys authentication methods.
|
|
537
|
+
*/
|
|
538
|
+
get passkeys() {
|
|
539
|
+
return this._passkeys;
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
// src/modules/user/index.ts
|
|
544
|
+
var UserModule = class {
|
|
545
|
+
/**
|
|
546
|
+
* Initializes a new instance of the `UserModule` class.
|
|
547
|
+
*
|
|
548
|
+
* @param {WebSignerClient} _webSignerClient underlying WebSigner client instance.
|
|
549
|
+
*/
|
|
550
|
+
constructor(_webSignerClient) {
|
|
551
|
+
this._webSignerClient = _webSignerClient;
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Gets the user information.
|
|
555
|
+
*
|
|
556
|
+
* @returns {User | undefined} user information.
|
|
557
|
+
*/
|
|
558
|
+
get info() {
|
|
559
|
+
return this._webSignerClient.user;
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
// src/index.ts
|
|
564
|
+
var FourtWebSigner = class {
|
|
565
|
+
_webSignerClient;
|
|
566
|
+
_modules;
|
|
567
|
+
/**
|
|
568
|
+
* Initializes a new instance of the `FourtWebSigner` class.
|
|
569
|
+
* Sets up the underlying modules.
|
|
570
|
+
*
|
|
571
|
+
*
|
|
572
|
+
* @example
|
|
573
|
+
* ```ts
|
|
574
|
+
* const fourtWebSigner = new FourtWebSigner({
|
|
575
|
+
* auth: {
|
|
576
|
+
* webauthn: {
|
|
577
|
+
* rpId: 'localhost',
|
|
578
|
+
* },
|
|
579
|
+
* },
|
|
580
|
+
* configuration: {
|
|
581
|
+
* apiKey: '927d603c-6775-4210-8e13-8904ca985e78',
|
|
582
|
+
* },
|
|
583
|
+
* })
|
|
584
|
+
* ```
|
|
585
|
+
*
|
|
586
|
+
* @param {FourtWebSignerConstructorParams} params the required parameters to initialize the client
|
|
587
|
+
*/
|
|
588
|
+
constructor({
|
|
589
|
+
configuration,
|
|
590
|
+
auth: { webauthn }
|
|
591
|
+
}) {
|
|
592
|
+
this._webSignerClient = new WebSignerClient({
|
|
593
|
+
configuration,
|
|
594
|
+
webauthn
|
|
595
|
+
});
|
|
596
|
+
this._modules = {
|
|
597
|
+
viem: new ViemModule(this._webSignerClient),
|
|
598
|
+
auth: new AuthModule(this._webSignerClient),
|
|
599
|
+
user: new UserModule(this._webSignerClient)
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* A module for interacting with the Viem library.
|
|
604
|
+
*/
|
|
605
|
+
get viem() {
|
|
606
|
+
return this._modules.viem;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* A module for interacting with the authentication methods.
|
|
610
|
+
*/
|
|
611
|
+
get auth() {
|
|
612
|
+
return this._modules.auth;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* A module for interacting with the user methods.
|
|
616
|
+
*/
|
|
617
|
+
get user() {
|
|
618
|
+
return this._modules.user;
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
622
|
+
0 && (module.exports = {
|
|
623
|
+
FourtWebSigner
|
|
624
|
+
});
|
|
625
|
+
//# sourceMappingURL=index.cjs.map
|