unwallet-client-sdk 0.21.0 → 0.23.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.cjs CHANGED
@@ -1,77 +1,107 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
2
24
  let viem = require("viem");
3
25
  let zod = require("zod");
26
+ zod = __toESM(zod, 1);
4
27
  //#region src/error.ts
5
28
  var UWError = class extends Error {
6
29
  static {
7
30
  this.prototype.name = "UWError";
8
31
  }
9
- constructor(code, message) {
10
- super(message !== void 0 ? `${code}: ${message}` : code);
32
+ constructor(code, msg) {
33
+ super(msg !== void 0 ? `${code}: ${msg}` : code);
11
34
  this.code = code;
12
35
  }
13
36
  };
14
37
  //#endregion
15
38
  //#region src/config.ts
16
- function getUnWalletConfigByEnv(env) {
17
- switch (env) {
18
- case "prod": return {
19
- frontend: { baseURL: "https://id.unwallet.world" },
20
- xAPI: {
21
- url: "wss://xapi.id.unwallet.world",
22
- connectionTimeout: 1e4
23
- }
24
- };
25
- case "dev": return {
26
- frontend: { baseURL: "http://localhost:4200" },
27
- xAPI: {
28
- url: "wss://xapi.id.test.unwallet.dev",
29
- connectionTimeout: 1e4
30
- }
31
- };
39
+ const envToUnWalletConfig = {
40
+ prod: {
41
+ frontend: { origin: "https://id.unwallet.world" },
42
+ xAPI: {
43
+ url: "wss://xapi.id.unwallet.world",
44
+ connectionTimeout: 1e4
45
+ }
46
+ },
47
+ dev: {
48
+ frontend: { origin: "http://localhost:4200" },
49
+ xAPI: {
50
+ url: "wss://xapi.id.test.unwallet.dev",
51
+ connectionTimeout: 1e4
52
+ }
32
53
  }
33
- }
34
- const xRequestSchema = zod.z.object({ action: zod.z.enum(["getConnectionID"]) });
35
- zod.z.string().refine((val) => {
54
+ };
55
+ const xRequestSchema = zod.object({ action: zod.enum(["getConnectionID"]) }).readonly();
56
+ zod.string().transform((val, ctx) => {
36
57
  try {
37
- JSON.parse(val);
58
+ return JSON.parse(val);
38
59
  } catch {
39
- return false;
60
+ ctx.addIssue({
61
+ code: "custom",
62
+ message: "Invalid JSON string"
63
+ });
64
+ return zod.NEVER;
40
65
  }
41
- return true;
42
- }, {
43
- abort: true,
44
- message: "Invalid JSON string"
45
- }).transform((val) => JSON.parse(val)).pipe(xRequestSchema);
46
- const xResponseSchema = zod.z.object({
47
- type: zod.z.enum([
48
- "connectionID",
49
- "signature",
50
- "transactionID",
51
- "error"
52
- ]),
53
- value: zod.z.string()
54
- });
55
- const xResponsePayloadSchema = zod.z.string().refine((val) => {
66
+ }).pipe(xRequestSchema);
67
+ const xResponseSchema = zod.union([
68
+ zod.object({
69
+ type: zod.literal("connectionID"),
70
+ value: zod.string().nonempty()
71
+ }),
72
+ zod.object({
73
+ type: zod.literal("signature"),
74
+ value: zod.string().refine(viem.isHex, { error: "Invalid hex" })
75
+ }),
76
+ zod.object({
77
+ type: zod.literal("transactionID"),
78
+ value: zod.string().nonempty()
79
+ }),
80
+ zod.object({
81
+ type: zod.literal("error"),
82
+ value: zod.string().nonempty()
83
+ })
84
+ ]).readonly();
85
+ const xResponsePayloadSchema = zod.string().transform((val, ctx) => {
56
86
  try {
57
- JSON.parse(val);
58
- } catch (e) {
59
- return false;
87
+ return JSON.parse(val);
88
+ } catch {
89
+ ctx.addIssue({
90
+ code: "custom",
91
+ message: "Invalid JSON string"
92
+ });
93
+ return zod.NEVER;
60
94
  }
61
- return true;
62
- }, {
63
- abort: true,
64
- message: "Invalid JSON string"
65
- }).transform((val) => JSON.parse(val)).pipe(xResponseSchema);
95
+ }).pipe(xResponseSchema);
66
96
  var XConnection = class XConnection {
67
97
  constructor(args) {
68
98
  this.responseHandler = null;
69
99
  this.id = args.id;
70
100
  this.socket = args.socket;
71
- this.options = args.options ?? {};
101
+ this.debugOptions = args.debugOptions ?? null;
72
102
  this.initListeners();
73
103
  }
74
- static async init(config, opts) {
104
+ static async init(config) {
75
105
  const socket = new WebSocket(config.url);
76
106
  const id = await new Promise((resolve, reject) => {
77
107
  const timeoutID = setTimeout(() => abortHandshake(new UWError("CONNECTION_TIMEOUT")), config.connectionTimeout);
@@ -115,14 +145,14 @@ var XConnection = class XConnection {
115
145
  return new XConnection({
116
146
  id,
117
147
  socket,
118
- options: opts
148
+ debugOptions: config.debug
119
149
  });
120
150
  }
121
151
  initListeners() {
122
152
  this.socket.onopen = null;
123
153
  this.socket.onmessage = (event) => {
124
154
  if (this.responseHandler === null) {
125
- this.options.debugHandlers?.onMessageEventDropped?.(event);
155
+ this.debugOptions?.handlers?.onMessageEventDropped?.(event);
126
156
  return;
127
157
  }
128
158
  let resp;
@@ -149,7 +179,7 @@ var XConnection = class XConnection {
149
179
  this.socket.onerror = null;
150
180
  this.socket.onclose = (event) => {
151
181
  if (this.responseHandler === null) {
152
- this.options.debugHandlers?.onCloseEventDropped?.(event);
182
+ this.debugOptions?.handlers?.onCloseEventDropped?.(event);
153
183
  return;
154
184
  }
155
185
  this.responseHandler.reject(newConnectionClosedError(event));
@@ -161,8 +191,8 @@ var XConnection = class XConnection {
161
191
  get hasResponseHandler() {
162
192
  return this.responseHandler !== null;
163
193
  }
164
- setResponseHandler(handler) {
165
- this.responseHandler = handler;
194
+ setResponseHandler(respHandler) {
195
+ this.responseHandler = respHandler;
166
196
  }
167
197
  close() {
168
198
  this.socket.close();
@@ -172,7 +202,7 @@ function safeParseXResponsePayload(data) {
172
202
  const result = xResponsePayloadSchema.safeParse(data);
173
203
  if (!result.success) return {
174
204
  success: false,
175
- error: new UWError("INVALID_RESPONSE", `invalid payload: ${zod.z.prettifyError(result.error)}`)
205
+ error: new UWError("INVALID_RESPONSE", `invalid payload: ${zod.prettifyError(result.error)}`)
176
206
  };
177
207
  return {
178
208
  success: true,
@@ -180,9 +210,10 @@ function safeParseXResponsePayload(data) {
180
210
  };
181
211
  }
182
212
  function newUnexpectedXResponseTypeError(resp) {
183
- let msg = `unexpected type: ${resp.type}`;
184
- if (resp.type === "error") msg += ` (value: ${resp.value})`;
185
- return new UWError("INVALID_RESPONSE", msg);
213
+ const msgs = [];
214
+ msgs.push(`unexpected type: ${resp.type}`);
215
+ if (resp.type === "error") msgs.push(`(value: ${resp.value})`);
216
+ return new UWError("INVALID_RESPONSE", msgs.join(" "));
186
217
  }
187
218
  function newConnectionClosedError(event) {
188
219
  return new UWError("CONNECTION_CLOSED", event.reason.length > 0 ? event.reason : void 0);
@@ -200,14 +231,14 @@ var UnWallet = class UnWallet {
200
231
  return new UnWallet({
201
232
  env,
202
233
  clientID: config.clientID,
203
- xConnection: await XConnection.init(getUnWalletConfigByEnv(env).xAPI)
234
+ xConnection: await XConnection.init(envToUnWalletConfig[env].xAPI)
204
235
  });
205
236
  }
206
237
  get unWalletConfig() {
207
- return getUnWalletConfigByEnv(this.env);
238
+ return envToUnWalletConfig[this.env];
208
239
  }
209
240
  authorize(args) {
210
- const url = new URL(`${this.unWalletConfig.frontend.baseURL}/${args.isVirtual === false ? "" : "v"}authorize`);
241
+ const url = new URL(`/${args.isVirtual === false ? "" : "v"}authorize`, this.unWalletConfig.frontend.origin);
211
242
  url.searchParams.set("response_type", "id_token");
212
243
  url.searchParams.set("response_mode", args.responseMode ?? "fragment");
213
244
  url.searchParams.set("client_id", this.clientID);
@@ -217,90 +248,57 @@ var UnWallet = class UnWallet {
217
248
  if (args.chainID !== void 0) url.searchParams.set("chain_id", args.chainID.toString());
218
249
  location.assign(url);
219
250
  }
220
- sign(args) {
221
- return new Promise((resolve, reject) => {
222
- if (this.xConnection.readyState !== WebSocket.OPEN) {
223
- reject(new UWError("CONNECTION_NOT_OPENED"));
224
- return;
225
- }
226
- if (this.xConnection.hasResponseHandler) {
227
- reject(new UWError("REQUEST_IN_PROGRESS"));
228
- return;
229
- }
230
- const digest = (0, viem.sha256)((0, viem.toBytes)(args.message));
231
- this.xConnection.setResponseHandler({
232
- resolve: (resp) => {
233
- this.xConnection.setResponseHandler(null);
234
- if (resp.type !== "signature") {
235
- reject(newUnexpectedXResponseTypeError(resp));
236
- return;
237
- }
238
- resolve({
239
- digest,
240
- signature: resp.value
241
- });
242
- },
243
- reject: (err) => {
244
- this.xConnection.setResponseHandler(null);
245
- reject(err);
251
+ async sign(args) {
252
+ return {
253
+ digest: (0, viem.sha256)((0, viem.toBytes)(args.message)),
254
+ signature: await this.request({
255
+ responseType: "signature",
256
+ path: "/x/sign",
257
+ params: {
258
+ message: args.message,
259
+ ticketToken: args.ticketToken
246
260
  }
247
- });
248
- const url = new URL(`${this.unWalletConfig.frontend.baseURL}/x/sign`);
249
- url.searchParams.set("connectionID", this.xConnection.id);
250
- url.searchParams.set("clientID", this.clientID);
251
- url.searchParams.set("message", args.message);
252
- url.searchParams.set("ticketToken", args.ticketToken);
253
- openWindow(url);
254
- });
261
+ })
262
+ };
255
263
  }
256
- signEIP712TypedData(args) {
257
- return new Promise((resolve, reject) => {
258
- if (this.xConnection.readyState !== WebSocket.OPEN) {
259
- reject(new UWError("CONNECTION_NOT_OPENED"));
260
- return;
261
- }
262
- if (this.xConnection.hasResponseHandler) {
263
- reject(new UWError("REQUEST_IN_PROGRESS"));
264
- return;
265
- }
266
- const { EIP712Domain: _, ...typedDataTypes } = args.typedData.types;
267
- const typedData = {
268
- ...args.typedData,
269
- types: typedDataTypes
270
- };
271
- try {
272
- (0, viem.validateTypedData)(typedData);
273
- } catch (e) {
274
- reject(new UWError("INVALID_REQUEST", `invalid typed data: ${e instanceof viem.BaseError ? e.shortMessage : String(e)}`));
275
- return;
276
- }
277
- const digest = (0, viem.hashTypedData)(typedData);
278
- this.xConnection.setResponseHandler({
279
- resolve: (resp) => {
280
- this.xConnection.setResponseHandler(null);
281
- if (resp.type !== "signature") {
282
- reject(newUnexpectedXResponseTypeError(resp));
283
- return;
284
- }
285
- resolve({
286
- digest,
287
- signature: resp.value
288
- });
289
- },
290
- reject: (err) => {
291
- this.xConnection.setResponseHandler(null);
292
- reject(err);
264
+ async signEIP712TypedData(args) {
265
+ const { EIP712Domain: _, ...typedDataTypes } = args.typedData.types;
266
+ const typedData = {
267
+ ...args.typedData,
268
+ types: typedDataTypes
269
+ };
270
+ try {
271
+ (0, viem.validateTypedData)(typedData);
272
+ } catch (e) {
273
+ throw new UWError("INVALID_REQUEST", `invalid typed data: ${e instanceof viem.BaseError ? e.shortMessage : String(e)}`);
274
+ }
275
+ return {
276
+ digest: (0, viem.hashTypedData)(typedData),
277
+ signature: await this.request({
278
+ responseType: "signature",
279
+ path: "/x/signEIP712TypedData",
280
+ params: {
281
+ typedData: JSON.stringify(args.typedData),
282
+ ticketToken: args.ticketToken
293
283
  }
294
- });
295
- const url = new URL(`${this.unWalletConfig.frontend.baseURL}/x/signEIP712TypedData`);
296
- url.searchParams.set("connectionID", this.xConnection.id);
297
- url.searchParams.set("clientID", this.clientID);
298
- url.searchParams.set("typedData", JSON.stringify(args.typedData));
299
- url.searchParams.set("ticketToken", args.ticketToken);
300
- openWindow(url);
301
- });
284
+ })
285
+ };
286
+ }
287
+ async sendTransaction(args) {
288
+ if (args.value === void 0 && args.data === void 0) throw new UWError("INVALID_REQUEST", "either value or data is required");
289
+ return { transactionID: await this.request({
290
+ responseType: "transactionID",
291
+ path: "/x/sendTransaction",
292
+ params: {
293
+ chainID: args.chainID.toString(),
294
+ toAddress: args.toAddress,
295
+ value: args.value ?? "0x0",
296
+ data: args.data ?? "0x",
297
+ ticketToken: args.ticketToken
298
+ }
299
+ }) };
302
300
  }
303
- sendTransaction(args) {
301
+ request(args) {
304
302
  return new Promise((resolve, reject) => {
305
303
  if (this.xConnection.readyState !== WebSocket.OPEN) {
306
304
  reject(new UWError("CONNECTION_NOT_OPENED"));
@@ -310,45 +308,31 @@ var UnWallet = class UnWallet {
310
308
  reject(new UWError("REQUEST_IN_PROGRESS"));
311
309
  return;
312
310
  }
313
- if (args.value === void 0 && args.data === void 0) {
314
- reject(new UWError("INVALID_REQUEST", "either value or data is required"));
315
- return;
316
- }
317
311
  this.xConnection.setResponseHandler({
318
312
  resolve: (resp) => {
319
313
  this.xConnection.setResponseHandler(null);
320
- if (resp.type !== "transactionID") {
314
+ if (resp.type !== args.responseType) {
321
315
  reject(newUnexpectedXResponseTypeError(resp));
322
316
  return;
323
317
  }
324
- resolve({ transactionID: resp.value });
318
+ resolve(resp.value);
325
319
  },
326
320
  reject: (err) => {
327
321
  this.xConnection.setResponseHandler(null);
328
322
  reject(err);
329
323
  }
330
324
  });
331
- const url = new URL(`${this.unWalletConfig.frontend.baseURL}/x/sendTransaction`);
325
+ const url = new URL(args.path, this.unWalletConfig.frontend.origin);
332
326
  url.searchParams.set("connectionID", this.xConnection.id);
333
327
  url.searchParams.set("clientID", this.clientID);
334
- url.searchParams.set("chainID", args.chainID.toString());
335
- url.searchParams.set("toAddress", args.toAddress);
336
- url.searchParams.set("value", args.value ?? "0x0");
337
- url.searchParams.set("data", args.data ?? "0x");
338
- url.searchParams.set("ticketToken", args.ticketToken);
339
- openWindow(url);
328
+ for (const [key, value] of Object.entries(args.params)) url.searchParams.set(key, value);
329
+ window.open(url.toString());
340
330
  });
341
331
  }
342
332
  close() {
343
333
  this.xConnection.close();
344
334
  }
345
335
  };
346
- function openWindow(url) {
347
- const width = screen.width / 2;
348
- const height = screen.height;
349
- const left = screen.width / 4;
350
- window.open(url.toString(), "_blank", `width=${width},height=${height},left=${left},top=0`);
351
- }
352
336
  //#endregion
353
337
  exports.UWError = UWError;
354
338
  exports.UnWallet = UnWallet;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { Address, Hex } from "viem";
2
- import { z } from "zod";
1
+ import { Address, Hash, Hex } from "viem";
2
+ import * as z from "zod";
3
3
  //#region src/config.d.ts
4
4
  type Env = "prod" | "dev";
5
5
  interface Config {
@@ -32,94 +32,101 @@ interface EIP712TypedDataField {
32
32
  //#endregion
33
33
  //#region src/error.d.ts
34
34
  type UWErrorCode = "CONNECTION_TIMEOUT" | "CONNECTION_FAILED" | "CONNECTION_NOT_OPENED" | "CONNECTION_CLOSED" | "INVALID_REQUEST" | "REQUEST_IN_PROGRESS" | "REQUEST_REJECTED" | "INVALID_RESPONSE";
35
- declare class UWError extends Error {
35
+ export declare class UWError extends Error {
36
36
  readonly code: UWErrorCode;
37
- constructor(code: UWErrorCode, message?: string);
37
+ constructor(code: UWErrorCode, msg?: string);
38
38
  }
39
39
  //#endregion
40
- //#region src/x.d.ts
41
- declare const xResponseSchema: z.ZodObject<{
42
- type: z.ZodEnum<{
43
- connectionID: "connectionID";
44
- error: "error";
45
- signature: "signature";
46
- transactionID: "transactionID";
47
- }>;
40
+ //#region src/xconn.d.ts
41
+ declare const xResponseSchema: z.ZodReadonly<z.ZodUnion<readonly [z.ZodObject<{
42
+ type: z.ZodLiteral<"connectionID">;
48
43
  value: z.ZodString;
49
- }, z.core.$strip>;
44
+ }, z.core.$strip>, z.ZodObject<{
45
+ type: z.ZodLiteral<"signature">;
46
+ value: z.ZodString & z.ZodType<`0x${string}`, string, z.core.$ZodTypeInternals<`0x${string}`, string>>;
47
+ }, z.core.$strip>, z.ZodObject<{
48
+ type: z.ZodLiteral<"transactionID">;
49
+ value: z.ZodString;
50
+ }, z.core.$strip>, z.ZodObject<{
51
+ type: z.ZodLiteral<"error">;
52
+ value: z.ZodString;
53
+ }, z.core.$strip>]>>;
50
54
  type XResponse = z.infer<typeof xResponseSchema>;
51
55
  type XResponseHandler = {
52
- resolve: (resp: XResponse) => void;
53
- reject: (err: UWError) => void;
56
+ readonly resolve: (resp: XResponse) => void;
57
+ readonly reject: (err: UWError) => void;
54
58
  };
55
- type XConnectionOptions = {
56
- debugHandlers?: XConnectionDebugHandlers;
59
+ type XConnectionDebugOptions = {
60
+ readonly handlers?: XConnectionDebugHandlers;
57
61
  };
58
62
  type XConnectionDebugHandlers = {
59
- onMessageEventDropped?: (event: MessageEvent) => void;
60
- onCloseEventDropped?: (event: CloseEvent) => void;
63
+ readonly onMessageEventDropped?: (event: MessageEvent) => void;
64
+ readonly onCloseEventDropped?: (event: CloseEvent) => void;
61
65
  };
62
66
  declare class XConnection {
63
67
  readonly id: string;
64
68
  private readonly socket;
65
- private readonly options;
69
+ private readonly debugOptions;
66
70
  private responseHandler;
67
71
  constructor(args: {
68
- id: string;
69
- socket: WebSocket;
70
- options?: XConnectionOptions | undefined;
72
+ readonly id: string;
73
+ readonly socket: WebSocket;
74
+ readonly debugOptions?: XConnectionDebugOptions | undefined;
71
75
  });
72
- static init(config: UnWalletXAPIConfig, opts?: XConnectionOptions): Promise<XConnection>;
76
+ static init(config: UnWalletXAPIConfig & {
77
+ readonly debug?: XConnectionDebugOptions | undefined;
78
+ }): Promise<XConnection>;
73
79
  private initListeners;
74
80
  get readyState(): number;
75
81
  get hasResponseHandler(): boolean;
76
- setResponseHandler(handler: XResponseHandler | null): void;
82
+ setResponseHandler(respHandler: XResponseHandler | null): void;
77
83
  close(): void;
78
84
  }
79
85
  //#endregion
80
86
  //#region src/unwallet.d.ts
81
87
  type AuthorizationResponseMode = "fragment" | "form_post";
82
88
  interface SignResult {
83
- digest: string;
84
- signature: string;
89
+ digest: Hash;
90
+ signature: Hex;
85
91
  }
86
92
  interface SendTransactionResult {
87
93
  transactionID: string;
88
94
  }
89
- declare class UnWallet {
90
- private env;
91
- private clientID;
92
- private xConnection;
95
+ export declare class UnWallet {
96
+ private readonly env;
97
+ private readonly clientID;
98
+ private readonly xConnection;
93
99
  constructor(args: {
94
- env: Env;
95
- clientID: string;
96
- xConnection: XConnection;
100
+ readonly env: Env;
101
+ readonly clientID: string;
102
+ readonly xConnection: XConnection;
97
103
  });
98
104
  static init(config: Config): Promise<UnWallet>;
99
105
  private get unWalletConfig();
100
106
  authorize(args: {
101
- responseMode?: AuthorizationResponseMode;
102
- redirectURL: string;
103
- nonce?: string;
104
- isVirtual?: boolean;
105
- chainID?: number;
107
+ readonly responseMode?: AuthorizationResponseMode;
108
+ readonly redirectURL: string;
109
+ readonly nonce?: string;
110
+ readonly isVirtual?: boolean;
111
+ readonly chainID?: number;
106
112
  }): void;
107
113
  sign(args: {
108
- message: string;
109
- ticketToken: string;
114
+ readonly message: string;
115
+ readonly ticketToken: string;
110
116
  }): Promise<SignResult>;
111
117
  signEIP712TypedData(args: {
112
- typedData: EIP712TypedData;
113
- ticketToken: string;
118
+ readonly typedData: EIP712TypedData;
119
+ readonly ticketToken: string;
114
120
  }): Promise<SignResult>;
115
121
  sendTransaction(args: {
116
- chainID: number;
117
- toAddress: string;
118
- value?: string;
119
- data?: string;
120
- ticketToken: string;
122
+ readonly chainID: number;
123
+ readonly toAddress: string;
124
+ readonly value?: string;
125
+ readonly data?: string;
126
+ readonly ticketToken: string;
121
127
  }): Promise<SendTransactionResult>;
128
+ private request;
122
129
  close(): void;
123
130
  }
124
131
  //#endregion
125
- export { type AuthorizationResponseMode, type Config, type EIP712TypedData, type EIP712TypedDataDomain, type EIP712TypedDataField, type Env, type SendTransactionResult, type SignResult, UWError, type UWErrorCode, UnWallet };
132
+ export type { AuthorizationResponseMode, Config, EIP712TypedData, EIP712TypedDataDomain, EIP712TypedDataField, Env, SendTransactionResult, SignResult, UWErrorCode };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Address, Hex } from "viem";
2
- import { z } from "zod";
1
+ import { Address, Hash, Hex } from "viem";
2
+ import * as z from "zod";
3
3
  //#region src/config.d.ts
4
4
  type Env = "prod" | "dev";
5
5
  interface Config {
@@ -32,94 +32,101 @@ interface EIP712TypedDataField {
32
32
  //#endregion
33
33
  //#region src/error.d.ts
34
34
  type UWErrorCode = "CONNECTION_TIMEOUT" | "CONNECTION_FAILED" | "CONNECTION_NOT_OPENED" | "CONNECTION_CLOSED" | "INVALID_REQUEST" | "REQUEST_IN_PROGRESS" | "REQUEST_REJECTED" | "INVALID_RESPONSE";
35
- declare class UWError extends Error {
35
+ export declare class UWError extends Error {
36
36
  readonly code: UWErrorCode;
37
- constructor(code: UWErrorCode, message?: string);
37
+ constructor(code: UWErrorCode, msg?: string);
38
38
  }
39
39
  //#endregion
40
- //#region src/x.d.ts
41
- declare const xResponseSchema: z.ZodObject<{
42
- type: z.ZodEnum<{
43
- connectionID: "connectionID";
44
- error: "error";
45
- signature: "signature";
46
- transactionID: "transactionID";
47
- }>;
40
+ //#region src/xconn.d.ts
41
+ declare const xResponseSchema: z.ZodReadonly<z.ZodUnion<readonly [z.ZodObject<{
42
+ type: z.ZodLiteral<"connectionID">;
48
43
  value: z.ZodString;
49
- }, z.core.$strip>;
44
+ }, z.core.$strip>, z.ZodObject<{
45
+ type: z.ZodLiteral<"signature">;
46
+ value: z.ZodString & z.ZodType<`0x${string}`, string, z.core.$ZodTypeInternals<`0x${string}`, string>>;
47
+ }, z.core.$strip>, z.ZodObject<{
48
+ type: z.ZodLiteral<"transactionID">;
49
+ value: z.ZodString;
50
+ }, z.core.$strip>, z.ZodObject<{
51
+ type: z.ZodLiteral<"error">;
52
+ value: z.ZodString;
53
+ }, z.core.$strip>]>>;
50
54
  type XResponse = z.infer<typeof xResponseSchema>;
51
55
  type XResponseHandler = {
52
- resolve: (resp: XResponse) => void;
53
- reject: (err: UWError) => void;
56
+ readonly resolve: (resp: XResponse) => void;
57
+ readonly reject: (err: UWError) => void;
54
58
  };
55
- type XConnectionOptions = {
56
- debugHandlers?: XConnectionDebugHandlers;
59
+ type XConnectionDebugOptions = {
60
+ readonly handlers?: XConnectionDebugHandlers;
57
61
  };
58
62
  type XConnectionDebugHandlers = {
59
- onMessageEventDropped?: (event: MessageEvent) => void;
60
- onCloseEventDropped?: (event: CloseEvent) => void;
63
+ readonly onMessageEventDropped?: (event: MessageEvent) => void;
64
+ readonly onCloseEventDropped?: (event: CloseEvent) => void;
61
65
  };
62
66
  declare class XConnection {
63
67
  readonly id: string;
64
68
  private readonly socket;
65
- private readonly options;
69
+ private readonly debugOptions;
66
70
  private responseHandler;
67
71
  constructor(args: {
68
- id: string;
69
- socket: WebSocket;
70
- options?: XConnectionOptions | undefined;
72
+ readonly id: string;
73
+ readonly socket: WebSocket;
74
+ readonly debugOptions?: XConnectionDebugOptions | undefined;
71
75
  });
72
- static init(config: UnWalletXAPIConfig, opts?: XConnectionOptions): Promise<XConnection>;
76
+ static init(config: UnWalletXAPIConfig & {
77
+ readonly debug?: XConnectionDebugOptions | undefined;
78
+ }): Promise<XConnection>;
73
79
  private initListeners;
74
80
  get readyState(): number;
75
81
  get hasResponseHandler(): boolean;
76
- setResponseHandler(handler: XResponseHandler | null): void;
82
+ setResponseHandler(respHandler: XResponseHandler | null): void;
77
83
  close(): void;
78
84
  }
79
85
  //#endregion
80
86
  //#region src/unwallet.d.ts
81
87
  type AuthorizationResponseMode = "fragment" | "form_post";
82
88
  interface SignResult {
83
- digest: string;
84
- signature: string;
89
+ digest: Hash;
90
+ signature: Hex;
85
91
  }
86
92
  interface SendTransactionResult {
87
93
  transactionID: string;
88
94
  }
89
- declare class UnWallet {
90
- private env;
91
- private clientID;
92
- private xConnection;
95
+ export declare class UnWallet {
96
+ private readonly env;
97
+ private readonly clientID;
98
+ private readonly xConnection;
93
99
  constructor(args: {
94
- env: Env;
95
- clientID: string;
96
- xConnection: XConnection;
100
+ readonly env: Env;
101
+ readonly clientID: string;
102
+ readonly xConnection: XConnection;
97
103
  });
98
104
  static init(config: Config): Promise<UnWallet>;
99
105
  private get unWalletConfig();
100
106
  authorize(args: {
101
- responseMode?: AuthorizationResponseMode;
102
- redirectURL: string;
103
- nonce?: string;
104
- isVirtual?: boolean;
105
- chainID?: number;
107
+ readonly responseMode?: AuthorizationResponseMode;
108
+ readonly redirectURL: string;
109
+ readonly nonce?: string;
110
+ readonly isVirtual?: boolean;
111
+ readonly chainID?: number;
106
112
  }): void;
107
113
  sign(args: {
108
- message: string;
109
- ticketToken: string;
114
+ readonly message: string;
115
+ readonly ticketToken: string;
110
116
  }): Promise<SignResult>;
111
117
  signEIP712TypedData(args: {
112
- typedData: EIP712TypedData;
113
- ticketToken: string;
118
+ readonly typedData: EIP712TypedData;
119
+ readonly ticketToken: string;
114
120
  }): Promise<SignResult>;
115
121
  sendTransaction(args: {
116
- chainID: number;
117
- toAddress: string;
118
- value?: string;
119
- data?: string;
120
- ticketToken: string;
122
+ readonly chainID: number;
123
+ readonly toAddress: string;
124
+ readonly value?: string;
125
+ readonly data?: string;
126
+ readonly ticketToken: string;
121
127
  }): Promise<SendTransactionResult>;
128
+ private request;
122
129
  close(): void;
123
130
  }
124
131
  //#endregion
125
- export { type AuthorizationResponseMode, type Config, type EIP712TypedData, type EIP712TypedDataDomain, type EIP712TypedDataField, type Env, type SendTransactionResult, type SignResult, UWError, type UWErrorCode, UnWallet };
132
+ export type { AuthorizationResponseMode, Config, EIP712TypedData, EIP712TypedDataDomain, EIP712TypedDataField, Env, SendTransactionResult, SignResult, UWErrorCode };
package/dist/index.js CHANGED
@@ -1,76 +1,83 @@
1
- import { BaseError, hashTypedData, sha256, toBytes, validateTypedData } from "viem";
2
- import { z } from "zod";
1
+ import { BaseError, hashTypedData, isHex, sha256, toBytes, validateTypedData } from "viem";
2
+ import * as z from "zod";
3
3
  //#region src/error.ts
4
4
  var UWError = class extends Error {
5
5
  static {
6
6
  this.prototype.name = "UWError";
7
7
  }
8
- constructor(code, message) {
9
- super(message !== void 0 ? `${code}: ${message}` : code);
8
+ constructor(code, msg) {
9
+ super(msg !== void 0 ? `${code}: ${msg}` : code);
10
10
  this.code = code;
11
11
  }
12
12
  };
13
13
  //#endregion
14
14
  //#region src/config.ts
15
- function getUnWalletConfigByEnv(env) {
16
- switch (env) {
17
- case "prod": return {
18
- frontend: { baseURL: "https://id.unwallet.world" },
19
- xAPI: {
20
- url: "wss://xapi.id.unwallet.world",
21
- connectionTimeout: 1e4
22
- }
23
- };
24
- case "dev": return {
25
- frontend: { baseURL: "http://localhost:4200" },
26
- xAPI: {
27
- url: "wss://xapi.id.test.unwallet.dev",
28
- connectionTimeout: 1e4
29
- }
30
- };
15
+ const envToUnWalletConfig = {
16
+ prod: {
17
+ frontend: { origin: "https://id.unwallet.world" },
18
+ xAPI: {
19
+ url: "wss://xapi.id.unwallet.world",
20
+ connectionTimeout: 1e4
21
+ }
22
+ },
23
+ dev: {
24
+ frontend: { origin: "http://localhost:4200" },
25
+ xAPI: {
26
+ url: "wss://xapi.id.test.unwallet.dev",
27
+ connectionTimeout: 1e4
28
+ }
31
29
  }
32
- }
33
- const xRequestSchema = z.object({ action: z.enum(["getConnectionID"]) });
34
- z.string().refine((val) => {
30
+ };
31
+ const xRequestSchema = z.object({ action: z.enum(["getConnectionID"]) }).readonly();
32
+ z.string().transform((val, ctx) => {
35
33
  try {
36
- JSON.parse(val);
34
+ return JSON.parse(val);
37
35
  } catch {
38
- return false;
36
+ ctx.addIssue({
37
+ code: "custom",
38
+ message: "Invalid JSON string"
39
+ });
40
+ return z.NEVER;
39
41
  }
40
- return true;
41
- }, {
42
- abort: true,
43
- message: "Invalid JSON string"
44
- }).transform((val) => JSON.parse(val)).pipe(xRequestSchema);
45
- const xResponseSchema = z.object({
46
- type: z.enum([
47
- "connectionID",
48
- "signature",
49
- "transactionID",
50
- "error"
51
- ]),
52
- value: z.string()
53
- });
54
- const xResponsePayloadSchema = z.string().refine((val) => {
42
+ }).pipe(xRequestSchema);
43
+ const xResponseSchema = z.union([
44
+ z.object({
45
+ type: z.literal("connectionID"),
46
+ value: z.string().nonempty()
47
+ }),
48
+ z.object({
49
+ type: z.literal("signature"),
50
+ value: z.string().refine(isHex, { error: "Invalid hex" })
51
+ }),
52
+ z.object({
53
+ type: z.literal("transactionID"),
54
+ value: z.string().nonempty()
55
+ }),
56
+ z.object({
57
+ type: z.literal("error"),
58
+ value: z.string().nonempty()
59
+ })
60
+ ]).readonly();
61
+ const xResponsePayloadSchema = z.string().transform((val, ctx) => {
55
62
  try {
56
- JSON.parse(val);
57
- } catch (e) {
58
- return false;
63
+ return JSON.parse(val);
64
+ } catch {
65
+ ctx.addIssue({
66
+ code: "custom",
67
+ message: "Invalid JSON string"
68
+ });
69
+ return z.NEVER;
59
70
  }
60
- return true;
61
- }, {
62
- abort: true,
63
- message: "Invalid JSON string"
64
- }).transform((val) => JSON.parse(val)).pipe(xResponseSchema);
71
+ }).pipe(xResponseSchema);
65
72
  var XConnection = class XConnection {
66
73
  constructor(args) {
67
74
  this.responseHandler = null;
68
75
  this.id = args.id;
69
76
  this.socket = args.socket;
70
- this.options = args.options ?? {};
77
+ this.debugOptions = args.debugOptions ?? null;
71
78
  this.initListeners();
72
79
  }
73
- static async init(config, opts) {
80
+ static async init(config) {
74
81
  const socket = new WebSocket(config.url);
75
82
  const id = await new Promise((resolve, reject) => {
76
83
  const timeoutID = setTimeout(() => abortHandshake(new UWError("CONNECTION_TIMEOUT")), config.connectionTimeout);
@@ -114,14 +121,14 @@ var XConnection = class XConnection {
114
121
  return new XConnection({
115
122
  id,
116
123
  socket,
117
- options: opts
124
+ debugOptions: config.debug
118
125
  });
119
126
  }
120
127
  initListeners() {
121
128
  this.socket.onopen = null;
122
129
  this.socket.onmessage = (event) => {
123
130
  if (this.responseHandler === null) {
124
- this.options.debugHandlers?.onMessageEventDropped?.(event);
131
+ this.debugOptions?.handlers?.onMessageEventDropped?.(event);
125
132
  return;
126
133
  }
127
134
  let resp;
@@ -148,7 +155,7 @@ var XConnection = class XConnection {
148
155
  this.socket.onerror = null;
149
156
  this.socket.onclose = (event) => {
150
157
  if (this.responseHandler === null) {
151
- this.options.debugHandlers?.onCloseEventDropped?.(event);
158
+ this.debugOptions?.handlers?.onCloseEventDropped?.(event);
152
159
  return;
153
160
  }
154
161
  this.responseHandler.reject(newConnectionClosedError(event));
@@ -160,8 +167,8 @@ var XConnection = class XConnection {
160
167
  get hasResponseHandler() {
161
168
  return this.responseHandler !== null;
162
169
  }
163
- setResponseHandler(handler) {
164
- this.responseHandler = handler;
170
+ setResponseHandler(respHandler) {
171
+ this.responseHandler = respHandler;
165
172
  }
166
173
  close() {
167
174
  this.socket.close();
@@ -179,9 +186,10 @@ function safeParseXResponsePayload(data) {
179
186
  };
180
187
  }
181
188
  function newUnexpectedXResponseTypeError(resp) {
182
- let msg = `unexpected type: ${resp.type}`;
183
- if (resp.type === "error") msg += ` (value: ${resp.value})`;
184
- return new UWError("INVALID_RESPONSE", msg);
189
+ const msgs = [];
190
+ msgs.push(`unexpected type: ${resp.type}`);
191
+ if (resp.type === "error") msgs.push(`(value: ${resp.value})`);
192
+ return new UWError("INVALID_RESPONSE", msgs.join(" "));
185
193
  }
186
194
  function newConnectionClosedError(event) {
187
195
  return new UWError("CONNECTION_CLOSED", event.reason.length > 0 ? event.reason : void 0);
@@ -199,14 +207,14 @@ var UnWallet = class UnWallet {
199
207
  return new UnWallet({
200
208
  env,
201
209
  clientID: config.clientID,
202
- xConnection: await XConnection.init(getUnWalletConfigByEnv(env).xAPI)
210
+ xConnection: await XConnection.init(envToUnWalletConfig[env].xAPI)
203
211
  });
204
212
  }
205
213
  get unWalletConfig() {
206
- return getUnWalletConfigByEnv(this.env);
214
+ return envToUnWalletConfig[this.env];
207
215
  }
208
216
  authorize(args) {
209
- const url = new URL(`${this.unWalletConfig.frontend.baseURL}/${args.isVirtual === false ? "" : "v"}authorize`);
217
+ const url = new URL(`/${args.isVirtual === false ? "" : "v"}authorize`, this.unWalletConfig.frontend.origin);
210
218
  url.searchParams.set("response_type", "id_token");
211
219
  url.searchParams.set("response_mode", args.responseMode ?? "fragment");
212
220
  url.searchParams.set("client_id", this.clientID);
@@ -216,90 +224,57 @@ var UnWallet = class UnWallet {
216
224
  if (args.chainID !== void 0) url.searchParams.set("chain_id", args.chainID.toString());
217
225
  location.assign(url);
218
226
  }
219
- sign(args) {
220
- return new Promise((resolve, reject) => {
221
- if (this.xConnection.readyState !== WebSocket.OPEN) {
222
- reject(new UWError("CONNECTION_NOT_OPENED"));
223
- return;
224
- }
225
- if (this.xConnection.hasResponseHandler) {
226
- reject(new UWError("REQUEST_IN_PROGRESS"));
227
- return;
228
- }
229
- const digest = sha256(toBytes(args.message));
230
- this.xConnection.setResponseHandler({
231
- resolve: (resp) => {
232
- this.xConnection.setResponseHandler(null);
233
- if (resp.type !== "signature") {
234
- reject(newUnexpectedXResponseTypeError(resp));
235
- return;
236
- }
237
- resolve({
238
- digest,
239
- signature: resp.value
240
- });
241
- },
242
- reject: (err) => {
243
- this.xConnection.setResponseHandler(null);
244
- reject(err);
227
+ async sign(args) {
228
+ return {
229
+ digest: sha256(toBytes(args.message)),
230
+ signature: await this.request({
231
+ responseType: "signature",
232
+ path: "/x/sign",
233
+ params: {
234
+ message: args.message,
235
+ ticketToken: args.ticketToken
245
236
  }
246
- });
247
- const url = new URL(`${this.unWalletConfig.frontend.baseURL}/x/sign`);
248
- url.searchParams.set("connectionID", this.xConnection.id);
249
- url.searchParams.set("clientID", this.clientID);
250
- url.searchParams.set("message", args.message);
251
- url.searchParams.set("ticketToken", args.ticketToken);
252
- openWindow(url);
253
- });
237
+ })
238
+ };
254
239
  }
255
- signEIP712TypedData(args) {
256
- return new Promise((resolve, reject) => {
257
- if (this.xConnection.readyState !== WebSocket.OPEN) {
258
- reject(new UWError("CONNECTION_NOT_OPENED"));
259
- return;
260
- }
261
- if (this.xConnection.hasResponseHandler) {
262
- reject(new UWError("REQUEST_IN_PROGRESS"));
263
- return;
264
- }
265
- const { EIP712Domain: _, ...typedDataTypes } = args.typedData.types;
266
- const typedData = {
267
- ...args.typedData,
268
- types: typedDataTypes
269
- };
270
- try {
271
- validateTypedData(typedData);
272
- } catch (e) {
273
- reject(new UWError("INVALID_REQUEST", `invalid typed data: ${e instanceof BaseError ? e.shortMessage : String(e)}`));
274
- return;
275
- }
276
- const digest = hashTypedData(typedData);
277
- this.xConnection.setResponseHandler({
278
- resolve: (resp) => {
279
- this.xConnection.setResponseHandler(null);
280
- if (resp.type !== "signature") {
281
- reject(newUnexpectedXResponseTypeError(resp));
282
- return;
283
- }
284
- resolve({
285
- digest,
286
- signature: resp.value
287
- });
288
- },
289
- reject: (err) => {
290
- this.xConnection.setResponseHandler(null);
291
- reject(err);
240
+ async signEIP712TypedData(args) {
241
+ const { EIP712Domain: _, ...typedDataTypes } = args.typedData.types;
242
+ const typedData = {
243
+ ...args.typedData,
244
+ types: typedDataTypes
245
+ };
246
+ try {
247
+ validateTypedData(typedData);
248
+ } catch (e) {
249
+ throw new UWError("INVALID_REQUEST", `invalid typed data: ${e instanceof BaseError ? e.shortMessage : String(e)}`);
250
+ }
251
+ return {
252
+ digest: hashTypedData(typedData),
253
+ signature: await this.request({
254
+ responseType: "signature",
255
+ path: "/x/signEIP712TypedData",
256
+ params: {
257
+ typedData: JSON.stringify(args.typedData),
258
+ ticketToken: args.ticketToken
292
259
  }
293
- });
294
- const url = new URL(`${this.unWalletConfig.frontend.baseURL}/x/signEIP712TypedData`);
295
- url.searchParams.set("connectionID", this.xConnection.id);
296
- url.searchParams.set("clientID", this.clientID);
297
- url.searchParams.set("typedData", JSON.stringify(args.typedData));
298
- url.searchParams.set("ticketToken", args.ticketToken);
299
- openWindow(url);
300
- });
260
+ })
261
+ };
262
+ }
263
+ async sendTransaction(args) {
264
+ if (args.value === void 0 && args.data === void 0) throw new UWError("INVALID_REQUEST", "either value or data is required");
265
+ return { transactionID: await this.request({
266
+ responseType: "transactionID",
267
+ path: "/x/sendTransaction",
268
+ params: {
269
+ chainID: args.chainID.toString(),
270
+ toAddress: args.toAddress,
271
+ value: args.value ?? "0x0",
272
+ data: args.data ?? "0x",
273
+ ticketToken: args.ticketToken
274
+ }
275
+ }) };
301
276
  }
302
- sendTransaction(args) {
277
+ request(args) {
303
278
  return new Promise((resolve, reject) => {
304
279
  if (this.xConnection.readyState !== WebSocket.OPEN) {
305
280
  reject(new UWError("CONNECTION_NOT_OPENED"));
@@ -309,44 +284,30 @@ var UnWallet = class UnWallet {
309
284
  reject(new UWError("REQUEST_IN_PROGRESS"));
310
285
  return;
311
286
  }
312
- if (args.value === void 0 && args.data === void 0) {
313
- reject(new UWError("INVALID_REQUEST", "either value or data is required"));
314
- return;
315
- }
316
287
  this.xConnection.setResponseHandler({
317
288
  resolve: (resp) => {
318
289
  this.xConnection.setResponseHandler(null);
319
- if (resp.type !== "transactionID") {
290
+ if (resp.type !== args.responseType) {
320
291
  reject(newUnexpectedXResponseTypeError(resp));
321
292
  return;
322
293
  }
323
- resolve({ transactionID: resp.value });
294
+ resolve(resp.value);
324
295
  },
325
296
  reject: (err) => {
326
297
  this.xConnection.setResponseHandler(null);
327
298
  reject(err);
328
299
  }
329
300
  });
330
- const url = new URL(`${this.unWalletConfig.frontend.baseURL}/x/sendTransaction`);
301
+ const url = new URL(args.path, this.unWalletConfig.frontend.origin);
331
302
  url.searchParams.set("connectionID", this.xConnection.id);
332
303
  url.searchParams.set("clientID", this.clientID);
333
- url.searchParams.set("chainID", args.chainID.toString());
334
- url.searchParams.set("toAddress", args.toAddress);
335
- url.searchParams.set("value", args.value ?? "0x0");
336
- url.searchParams.set("data", args.data ?? "0x");
337
- url.searchParams.set("ticketToken", args.ticketToken);
338
- openWindow(url);
304
+ for (const [key, value] of Object.entries(args.params)) url.searchParams.set(key, value);
305
+ window.open(url.toString());
339
306
  });
340
307
  }
341
308
  close() {
342
309
  this.xConnection.close();
343
310
  }
344
311
  };
345
- function openWindow(url) {
346
- const width = screen.width / 2;
347
- const height = screen.height;
348
- const left = screen.width / 4;
349
- window.open(url.toString(), "_blank", `width=${width},height=${height},left=${left},top=0`);
350
- }
351
312
  //#endregion
352
313
  export { UWError, UnWallet };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unwallet-client-sdk",
3
- "version": "0.21.0",
3
+ "version": "0.23.0",
4
4
  "description": "unWallet client-side SDK",
5
5
  "license": "MIT",
6
6
  "author": "SIVIRA",
@@ -29,22 +29,22 @@
29
29
  "url": "git+https://github.com/SIVIRA/unwallet-client-sdk-js.git"
30
30
  },
31
31
  "dependencies": {
32
- "viem": "2.55.10",
33
- "zod": "4.4.3"
32
+ "viem": "2.56.5",
33
+ "zod": "4.6.5"
34
34
  },
35
35
  "devDependencies": {
36
- "@commitlint/cli": "21.2.1",
37
- "@commitlint/config-conventional": "21.2.0",
36
+ "@commitlint/cli": "21.2.2",
37
+ "@commitlint/config-conventional": "21.2.2",
38
38
  "@commitlint/types": "21.2.0",
39
39
  "@tsconfig/strictest": "2.0.8",
40
- "@vitest/coverage-v8": "4.1.10",
41
- "czg": "1.13.1",
40
+ "@vitest/coverage-v8": "5.0.0",
41
+ "czg": "1.14.0",
42
42
  "husky": "9.1.7",
43
43
  "msw": "2.15.0",
44
- "publint": "0.3.23",
45
- "tsdown": "0.22.14",
44
+ "publint": "0.3.24",
45
+ "tsdown": "0.23.0",
46
46
  "typescript": "7.0.2",
47
- "vitest": "4.1.10"
47
+ "vitest": "5.0.0"
48
48
  },
49
49
  "scripts": {}
50
50
  }