@column-org/wallet-sdk 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -8,6 +8,7 @@ interface ColumnSDKConfig {
8
8
  appDescription?: string;
9
9
  walletScheme?: string;
10
10
  network?: string;
11
+ sessionSecretKey?: string;
11
12
  }
12
13
  declare class ColumnCrypto {
13
14
  static generateKeyPair(): nacl.BoxKeyPair;
@@ -22,13 +23,15 @@ declare class ColumnWalletSDK {
22
23
  private config;
23
24
  private sessionKeyPair;
24
25
  private walletEncryptionPublicKey;
25
- private modal;
26
26
  constructor(config: ColumnSDKConfig);
27
- private autoDetectMetadata;
28
27
  /**
29
- * Opens the premium Column selection modal
28
+ * Returns the current session's secret key (bs58) so it can be persisted
30
29
  */
31
- openConnectModal(): void;
30
+ getSessionSecretKey(): string;
31
+ /**
32
+ * Internal: Used by Web/Native adapters to get the config
33
+ */
34
+ getConfig(): ColumnSDKConfig;
32
35
  setWalletEncryptionPublicKey(key: string): void;
33
36
  /**
34
37
  * Alias for setWalletEncryptionPublicKey to match docs
@@ -56,4 +59,14 @@ declare class ColumnWalletSDK {
56
59
  setWalletPublicKey(publicKeyB58: string): void;
57
60
  }
58
61
 
59
- export { ColumnCrypto, type ColumnSDKConfig, ColumnWalletSDK };
62
+ /**
63
+ * Enhanced SDK Class specifically for Web environments
64
+ */
65
+ declare class ColumnWalletWeb extends ColumnWalletSDK {
66
+ private modal;
67
+ constructor(config: ColumnSDKConfig);
68
+ private static autoDetectMetadata;
69
+ openConnectModal(): void;
70
+ }
71
+
72
+ export { ColumnCrypto, type ColumnSDKConfig, ColumnWalletSDK, ColumnWalletWeb };
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ interface ColumnSDKConfig {
8
8
  appDescription?: string;
9
9
  walletScheme?: string;
10
10
  network?: string;
11
+ sessionSecretKey?: string;
11
12
  }
12
13
  declare class ColumnCrypto {
13
14
  static generateKeyPair(): nacl.BoxKeyPair;
@@ -22,13 +23,15 @@ declare class ColumnWalletSDK {
22
23
  private config;
23
24
  private sessionKeyPair;
24
25
  private walletEncryptionPublicKey;
25
- private modal;
26
26
  constructor(config: ColumnSDKConfig);
27
- private autoDetectMetadata;
28
27
  /**
29
- * Opens the premium Column selection modal
28
+ * Returns the current session's secret key (bs58) so it can be persisted
30
29
  */
31
- openConnectModal(): void;
30
+ getSessionSecretKey(): string;
31
+ /**
32
+ * Internal: Used by Web/Native adapters to get the config
33
+ */
34
+ getConfig(): ColumnSDKConfig;
32
35
  setWalletEncryptionPublicKey(key: string): void;
33
36
  /**
34
37
  * Alias for setWalletEncryptionPublicKey to match docs
@@ -56,4 +59,14 @@ declare class ColumnWalletSDK {
56
59
  setWalletPublicKey(publicKeyB58: string): void;
57
60
  }
58
61
 
59
- export { ColumnCrypto, type ColumnSDKConfig, ColumnWalletSDK };
62
+ /**
63
+ * Enhanced SDK Class specifically for Web environments
64
+ */
65
+ declare class ColumnWalletWeb extends ColumnWalletSDK {
66
+ private modal;
67
+ constructor(config: ColumnSDKConfig);
68
+ private static autoDetectMetadata;
69
+ openConnectModal(): void;
70
+ }
71
+
72
+ export { ColumnCrypto, type ColumnSDKConfig, ColumnWalletSDK, ColumnWalletWeb };
package/dist/index.js CHANGED
@@ -31,7 +31,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  ColumnCrypto: () => ColumnCrypto,
34
- ColumnWalletSDK: () => ColumnWalletSDK
34
+ ColumnWalletSDK: () => ColumnWalletSDK,
35
+ ColumnWalletWeb: () => ColumnWalletWeb
35
36
  });
36
37
  module.exports = __toCommonJS(index_exports);
37
38
 
@@ -70,8 +71,210 @@ var ColumnCrypto = class {
70
71
  sharedSecret
71
72
  );
72
73
  if (!decrypted) return null;
73
- const jsonString = import_buffer.Buffer.from(decrypted).toString("utf8");
74
- return JSON.parse(jsonString);
74
+ try {
75
+ const jsonString = import_buffer.Buffer.from(decrypted).toString("utf8");
76
+ return JSON.parse(jsonString);
77
+ } catch (e) {
78
+ console.error("ColumnCrypto: Failed to parse decrypted payload", e);
79
+ return null;
80
+ }
81
+ }
82
+ };
83
+
84
+ // src/ColumnWalletSDK.ts
85
+ var nacl2 = __toESM(require("tweetnacl"));
86
+ var ColumnWalletSDK = class {
87
+ config;
88
+ sessionKeyPair;
89
+ walletEncryptionPublicKey = null;
90
+ constructor(config) {
91
+ this.config = config;
92
+ if (config.sessionSecretKey) {
93
+ try {
94
+ const secretKey = import_bs582.default.decode(config.sessionSecretKey);
95
+ this.sessionKeyPair = nacl2.box.keyPair.fromSecretKey(secretKey);
96
+ } catch (e) {
97
+ console.warn("ColumnWalletSDK: Invalid sessionSecretKey provided, generating new one.");
98
+ this.sessionKeyPair = ColumnCrypto.generateKeyPair();
99
+ }
100
+ } else {
101
+ this.sessionKeyPair = ColumnCrypto.generateKeyPair();
102
+ }
103
+ }
104
+ /**
105
+ * Returns the current session's secret key (bs58) so it can be persisted
106
+ */
107
+ getSessionSecretKey() {
108
+ return import_bs582.default.encode(this.sessionKeyPair.secretKey);
109
+ }
110
+ /**
111
+ * Internal: Used by Web/Native adapters to get the config
112
+ */
113
+ getConfig() {
114
+ return this.config;
115
+ }
116
+ setWalletEncryptionPublicKey(key) {
117
+ this.walletEncryptionPublicKey = key;
118
+ }
119
+ /**
120
+ * Alias for setWalletEncryptionPublicKey to match docs
121
+ */
122
+ importWalletKey(key) {
123
+ this.setWalletEncryptionPublicKey(key);
124
+ }
125
+ /**
126
+ * Step 1: Connect to the wallet
127
+ */
128
+ connect() {
129
+ const params = new URLSearchParams({
130
+ request: "connect",
131
+ app_url: this.config.appUrl || "",
132
+ app_name: this.config.appName || "",
133
+ dapp_encryption_public_key: import_bs582.default.encode(this.sessionKeyPair.publicKey),
134
+ redirect_link: this.config.redirectLink || ""
135
+ });
136
+ if (this.config.appIcon) {
137
+ params.append("app_icon", this.config.appIcon);
138
+ }
139
+ if (this.config.network) {
140
+ params.append("network", this.config.network);
141
+ }
142
+ if (this.config.appDescription) {
143
+ params.append("app_description", this.config.appDescription);
144
+ }
145
+ const scheme = this.config.walletScheme || "column";
146
+ const base = scheme.includes("://") ? scheme : `${scheme}://`;
147
+ return `${base}${base.endsWith("/") ? "" : "/"}?${params.toString()}`;
148
+ }
149
+ /**
150
+ * Step 2: Sign and Submit a transaction
151
+ */
152
+ signAndSubmitTransaction(transaction) {
153
+ if (!this.walletEncryptionPublicKey) {
154
+ throw new Error("Wallet not connected. Call connect() first and store the wallet_encryption_public_key.");
155
+ }
156
+ const payload = {
157
+ transaction
158
+ };
159
+ const encrypted = ColumnCrypto.encryptPayload(
160
+ payload,
161
+ this.walletEncryptionPublicKey,
162
+ this.sessionKeyPair.secretKey
163
+ );
164
+ const params = new URLSearchParams({
165
+ request: "signAndSubmitTransaction",
166
+ app_url: this.config.appUrl || "",
167
+ app_name: this.config.appName || "",
168
+ dapp_encryption_public_key: import_bs582.default.encode(this.sessionKeyPair.publicKey),
169
+ data: encrypted.data,
170
+ nonce: encrypted.nonce,
171
+ redirect_link: this.config.redirectLink || ""
172
+ });
173
+ if (this.config.appIcon) {
174
+ params.append("app_icon", this.config.appIcon);
175
+ }
176
+ if (this.config.network) {
177
+ params.append("network", this.config.network);
178
+ }
179
+ if (this.config.appDescription) {
180
+ params.append("app_description", this.config.appDescription);
181
+ }
182
+ const scheme = this.config.walletScheme || "column";
183
+ const base = scheme.includes("://") ? scheme : `${scheme}://`;
184
+ return `${base}${base.endsWith("/") ? "" : "/"}?${params.toString()}`;
185
+ }
186
+ /**
187
+ * Step 3: Sign a simple message
188
+ */
189
+ signMessage(message) {
190
+ if (!this.walletEncryptionPublicKey) {
191
+ throw new Error("Wallet not connected.");
192
+ }
193
+ const payload = {
194
+ message
195
+ };
196
+ const encrypted = ColumnCrypto.encryptPayload(
197
+ payload,
198
+ this.walletEncryptionPublicKey,
199
+ this.sessionKeyPair.secretKey
200
+ );
201
+ const params = new URLSearchParams({
202
+ request: "signMessage",
203
+ app_url: this.config.appUrl || "",
204
+ app_name: this.config.appName || "",
205
+ dapp_encryption_public_key: import_bs582.default.encode(this.sessionKeyPair.publicKey),
206
+ data: encrypted.data,
207
+ nonce: encrypted.nonce,
208
+ redirect_link: this.config.redirectLink || ""
209
+ });
210
+ if (this.config.appIcon) {
211
+ params.append("app_icon", this.config.appIcon);
212
+ }
213
+ if (this.config.network) {
214
+ params.append("network", this.config.network);
215
+ }
216
+ if (this.config.appDescription) {
217
+ params.append("app_description", this.config.appDescription);
218
+ }
219
+ const scheme = this.config.walletScheme || "column";
220
+ const base = scheme.includes("://") ? scheme : `${scheme}://`;
221
+ return `${base}${base.endsWith("/") ? "" : "/"}?${params.toString()}`;
222
+ }
223
+ /**
224
+ * Utility: Parse the response from Column
225
+ */
226
+ handleResponse(url) {
227
+ let params;
228
+ try {
229
+ const urlObj = new URL(url.includes("://") ? url : `http://localhost/${url}`);
230
+ const hashStr = urlObj.hash.substring(1);
231
+ const searchStr = urlObj.search.substring(1);
232
+ if (hashStr) {
233
+ params = new URLSearchParams(hashStr);
234
+ } else {
235
+ params = new URLSearchParams(searchStr);
236
+ }
237
+ } catch (e) {
238
+ const hashMatch = url.match(/#(.*)$/);
239
+ const queryMatch = url.match(/\?(.*)$/);
240
+ params = new URLSearchParams(hashMatch ? hashMatch[1] : queryMatch ? queryMatch[1] : url);
241
+ }
242
+ const data = params.get("data");
243
+ const nonce = params.get("nonce");
244
+ const error = params.get("error");
245
+ if (error) {
246
+ throw new Error(`Column Wallet Error: ${error}`);
247
+ }
248
+ if (data && nonce && this.walletEncryptionPublicKey) {
249
+ const decrypted = ColumnCrypto.decryptPayload(
250
+ data,
251
+ nonce,
252
+ this.walletEncryptionPublicKey,
253
+ this.sessionKeyPair.secretKey
254
+ );
255
+ if (!decrypted) {
256
+ throw new Error("Column Wallet Error: Decryption failed. The response may have been tampered with or keys do not match.");
257
+ }
258
+ return {
259
+ ...decrypted,
260
+ network: params.get("network")
261
+ // Always include network from URL
262
+ };
263
+ }
264
+ const response = {};
265
+ params.forEach((value, key) => {
266
+ response[key] = value;
267
+ });
268
+ if (response.column_encryption_public_key) {
269
+ this.walletEncryptionPublicKey = response.column_encryption_public_key;
270
+ }
271
+ return response;
272
+ }
273
+ /**
274
+ * Sets the wallet's public key if known from a previous session
275
+ */
276
+ setWalletPublicKey(publicKeyB58) {
277
+ this.walletEncryptionPublicKey = publicKeyB58;
75
278
  }
76
279
  };
77
280
 
@@ -210,7 +413,7 @@ var ColumnConnectModal = class {
210
413
  document.head.appendChild(styleTag);
211
414
  }
212
415
  open() {
213
- if (typeof document === "undefined") return;
416
+ if (typeof document === "undefined" || this.overlay) return;
214
417
  this.overlay = document.createElement("div");
215
418
  this.overlay.className = "column-modal-overlay";
216
419
  this.overlay.innerHTML = `
@@ -257,218 +460,31 @@ var ColumnConnectModal = class {
257
460
  }
258
461
  };
259
462
 
260
- // src/ColumnWalletSDK.ts
261
- var ColumnWalletSDK = class {
262
- config;
263
- sessionKeyPair;
264
- walletEncryptionPublicKey = null;
463
+ // src/ui/ColumnWalletWeb.ts
464
+ var ColumnWalletWeb = class _ColumnWalletWeb extends ColumnWalletSDK {
265
465
  modal;
266
466
  constructor(config) {
267
- this.config = this.autoDetectMetadata(config);
268
- this.sessionKeyPair = ColumnCrypto.generateKeyPair();
467
+ const detectedConfig = _ColumnWalletWeb.autoDetectMetadata(config);
468
+ super(detectedConfig);
269
469
  this.modal = new ColumnConnectModal(() => {
270
470
  window.location.href = this.connect();
271
471
  });
272
472
  }
273
- autoDetectMetadata(config) {
473
+ static autoDetectMetadata(config) {
274
474
  if (typeof document === "undefined") return config;
275
475
  const detectedConfig = { ...config };
276
- if (!detectedConfig.appUrl) {
277
- detectedConfig.appUrl = window.location.origin;
278
- }
279
- if (!detectedConfig.appName) {
280
- detectedConfig.appName = document.title || "Unknown dApp";
281
- }
282
- if (!detectedConfig.appIcon) {
283
- const iconLink = document.querySelector('link[rel~="icon"]') || document.querySelector('link[rel="apple-touch-icon"]');
284
- if (iconLink) {
285
- try {
286
- detectedConfig.appIcon = new URL(iconLink.getAttribute("href") || "", window.location.origin).href;
287
- } catch (e) {
288
- detectedConfig.appIcon = iconLink.href;
289
- }
290
- }
291
- }
292
- if (!detectedConfig.appDescription) {
293
- const metaDescription = document.querySelector('meta[name="description"]') || document.querySelector('meta[property="og:description"]');
294
- if (metaDescription?.content) {
295
- detectedConfig.appDescription = metaDescription.content;
296
- }
297
- }
298
- if (!detectedConfig.redirectLink) {
299
- detectedConfig.redirectLink = window.location.href.split("?")[0];
300
- }
476
+ if (!detectedConfig.appUrl) detectedConfig.appUrl = window.location.origin;
477
+ if (!detectedConfig.appName) detectedConfig.appName = document.title || "Unknown dApp";
478
+ if (!detectedConfig.redirectLink) detectedConfig.redirectLink = window.location.href.split("?")[0];
301
479
  return detectedConfig;
302
480
  }
303
- /**
304
- * Opens the premium Column selection modal
305
- */
306
481
  openConnectModal() {
307
482
  this.modal.open();
308
483
  }
309
- setWalletEncryptionPublicKey(key) {
310
- this.walletEncryptionPublicKey = key;
311
- }
312
- /**
313
- * Alias for setWalletEncryptionPublicKey to match docs
314
- */
315
- importWalletKey(key) {
316
- this.setWalletEncryptionPublicKey(key);
317
- }
318
- /**
319
- * Step 1: Connect to the wallet
320
- */
321
- connect() {
322
- const params = new URLSearchParams({
323
- request: "connect",
324
- app_url: this.config.appUrl || "",
325
- app_name: this.config.appName || "",
326
- dapp_encryption_public_key: import_bs582.default.encode(this.sessionKeyPair.publicKey),
327
- redirect_link: this.config.redirectLink || ""
328
- });
329
- if (this.config.appIcon) {
330
- params.append("app_icon", this.config.appIcon);
331
- }
332
- if (this.config.network) {
333
- params.append("network", this.config.network);
334
- }
335
- if (this.config.appDescription) {
336
- params.append("app_description", this.config.appDescription);
337
- }
338
- const scheme = this.config.walletScheme || "column";
339
- const base = scheme.includes("://") ? scheme : `${scheme}://`;
340
- return `${base}${base.endsWith("/") ? "" : "/"}?${params.toString()}`;
341
- }
342
- /**
343
- * Step 2: Sign and Submit a transaction
344
- */
345
- signAndSubmitTransaction(transaction) {
346
- if (!this.walletEncryptionPublicKey) {
347
- throw new Error("Wallet not connected. Call connect() first and store the wallet_encryption_public_key.");
348
- }
349
- const payload = {
350
- transaction
351
- };
352
- const encrypted = ColumnCrypto.encryptPayload(
353
- payload,
354
- this.walletEncryptionPublicKey,
355
- this.sessionKeyPair.secretKey
356
- );
357
- const params = new URLSearchParams({
358
- request: "signAndSubmitTransaction",
359
- app_url: this.config.appUrl || "",
360
- app_name: this.config.appName || "",
361
- dapp_encryption_public_key: import_bs582.default.encode(this.sessionKeyPair.publicKey),
362
- data: encrypted.data,
363
- nonce: encrypted.nonce,
364
- redirect_link: this.config.redirectLink || ""
365
- });
366
- if (this.config.appIcon) {
367
- params.append("app_icon", this.config.appIcon);
368
- }
369
- if (this.config.network) {
370
- params.append("network", this.config.network);
371
- }
372
- if (this.config.appDescription) {
373
- params.append("app_description", this.config.appDescription);
374
- }
375
- const scheme = this.config.walletScheme || "column";
376
- const base = scheme.includes("://") ? scheme : `${scheme}://`;
377
- return `${base}${base.endsWith("/") ? "" : "/"}?${params.toString()}`;
378
- }
379
- /**
380
- * Step 3: Sign a simple message
381
- */
382
- signMessage(message) {
383
- if (!this.walletEncryptionPublicKey) {
384
- throw new Error("Wallet not connected.");
385
- }
386
- const payload = {
387
- message
388
- };
389
- const encrypted = ColumnCrypto.encryptPayload(
390
- payload,
391
- this.walletEncryptionPublicKey,
392
- this.sessionKeyPair.secretKey
393
- );
394
- const params = new URLSearchParams({
395
- request: "signMessage",
396
- app_url: this.config.appUrl || "",
397
- app_name: this.config.appName || "",
398
- dapp_encryption_public_key: import_bs582.default.encode(this.sessionKeyPair.publicKey),
399
- data: encrypted.data,
400
- nonce: encrypted.nonce,
401
- redirect_link: this.config.redirectLink || ""
402
- });
403
- if (this.config.appIcon) {
404
- params.append("app_icon", this.config.appIcon);
405
- }
406
- if (this.config.network) {
407
- params.append("network", this.config.network);
408
- }
409
- if (this.config.appDescription) {
410
- params.append("app_description", this.config.appDescription);
411
- }
412
- const scheme = this.config.walletScheme || "column";
413
- const base = scheme.includes("://") ? scheme : `${scheme}://`;
414
- return `${base}${base.endsWith("/") ? "" : "/"}?${params.toString()}`;
415
- }
416
- /**
417
- * Utility: Parse the response from Column
418
- */
419
- handleResponse(url) {
420
- let params;
421
- try {
422
- const urlObj = new URL(url.includes("://") ? url : `http://localhost/${url}`);
423
- const hashStr = urlObj.hash.substring(1);
424
- const searchStr = urlObj.search.substring(1);
425
- if (hashStr) {
426
- params = new URLSearchParams(hashStr);
427
- } else {
428
- params = new URLSearchParams(searchStr);
429
- }
430
- } catch (e) {
431
- const hashMatch = url.match(/#(.*)$/);
432
- const queryMatch = url.match(/\?(.*)$/);
433
- params = new URLSearchParams(hashMatch ? hashMatch[1] : queryMatch ? queryMatch[1] : url);
434
- }
435
- const data = params.get("data");
436
- const nonce = params.get("nonce");
437
- const error = params.get("error");
438
- if (error) {
439
- throw new Error(`Column Wallet Error: ${error}`);
440
- }
441
- if (data && nonce && this.walletEncryptionPublicKey) {
442
- const decrypted = ColumnCrypto.decryptPayload(
443
- data,
444
- nonce,
445
- this.walletEncryptionPublicKey,
446
- this.sessionKeyPair.secretKey
447
- );
448
- return {
449
- ...decrypted,
450
- network: params.get("network")
451
- // Always include network from URL
452
- };
453
- }
454
- const response = {};
455
- params.forEach((value, key) => {
456
- response[key] = value;
457
- });
458
- if (response.column_encryption_public_key) {
459
- this.walletEncryptionPublicKey = response.column_encryption_public_key;
460
- }
461
- return response;
462
- }
463
- /**
464
- * Sets the wallet's public key if known from a previous session
465
- */
466
- setWalletPublicKey(publicKeyB58) {
467
- this.walletEncryptionPublicKey = publicKeyB58;
468
- }
469
484
  };
470
485
  // Annotate the CommonJS export names for ESM import in node:
471
486
  0 && (module.exports = {
472
487
  ColumnCrypto,
473
- ColumnWalletSDK
488
+ ColumnWalletSDK,
489
+ ColumnWalletWeb
474
490
  });
package/dist/index.mjs CHANGED
@@ -33,8 +33,210 @@ var ColumnCrypto = class {
33
33
  sharedSecret
34
34
  );
35
35
  if (!decrypted) return null;
36
- const jsonString = Buffer.from(decrypted).toString("utf8");
37
- return JSON.parse(jsonString);
36
+ try {
37
+ const jsonString = Buffer.from(decrypted).toString("utf8");
38
+ return JSON.parse(jsonString);
39
+ } catch (e) {
40
+ console.error("ColumnCrypto: Failed to parse decrypted payload", e);
41
+ return null;
42
+ }
43
+ }
44
+ };
45
+
46
+ // src/ColumnWalletSDK.ts
47
+ import * as nacl2 from "tweetnacl";
48
+ var ColumnWalletSDK = class {
49
+ config;
50
+ sessionKeyPair;
51
+ walletEncryptionPublicKey = null;
52
+ constructor(config) {
53
+ this.config = config;
54
+ if (config.sessionSecretKey) {
55
+ try {
56
+ const secretKey = bs582.decode(config.sessionSecretKey);
57
+ this.sessionKeyPair = nacl2.box.keyPair.fromSecretKey(secretKey);
58
+ } catch (e) {
59
+ console.warn("ColumnWalletSDK: Invalid sessionSecretKey provided, generating new one.");
60
+ this.sessionKeyPair = ColumnCrypto.generateKeyPair();
61
+ }
62
+ } else {
63
+ this.sessionKeyPair = ColumnCrypto.generateKeyPair();
64
+ }
65
+ }
66
+ /**
67
+ * Returns the current session's secret key (bs58) so it can be persisted
68
+ */
69
+ getSessionSecretKey() {
70
+ return bs582.encode(this.sessionKeyPair.secretKey);
71
+ }
72
+ /**
73
+ * Internal: Used by Web/Native adapters to get the config
74
+ */
75
+ getConfig() {
76
+ return this.config;
77
+ }
78
+ setWalletEncryptionPublicKey(key) {
79
+ this.walletEncryptionPublicKey = key;
80
+ }
81
+ /**
82
+ * Alias for setWalletEncryptionPublicKey to match docs
83
+ */
84
+ importWalletKey(key) {
85
+ this.setWalletEncryptionPublicKey(key);
86
+ }
87
+ /**
88
+ * Step 1: Connect to the wallet
89
+ */
90
+ connect() {
91
+ const params = new URLSearchParams({
92
+ request: "connect",
93
+ app_url: this.config.appUrl || "",
94
+ app_name: this.config.appName || "",
95
+ dapp_encryption_public_key: bs582.encode(this.sessionKeyPair.publicKey),
96
+ redirect_link: this.config.redirectLink || ""
97
+ });
98
+ if (this.config.appIcon) {
99
+ params.append("app_icon", this.config.appIcon);
100
+ }
101
+ if (this.config.network) {
102
+ params.append("network", this.config.network);
103
+ }
104
+ if (this.config.appDescription) {
105
+ params.append("app_description", this.config.appDescription);
106
+ }
107
+ const scheme = this.config.walletScheme || "column";
108
+ const base = scheme.includes("://") ? scheme : `${scheme}://`;
109
+ return `${base}${base.endsWith("/") ? "" : "/"}?${params.toString()}`;
110
+ }
111
+ /**
112
+ * Step 2: Sign and Submit a transaction
113
+ */
114
+ signAndSubmitTransaction(transaction) {
115
+ if (!this.walletEncryptionPublicKey) {
116
+ throw new Error("Wallet not connected. Call connect() first and store the wallet_encryption_public_key.");
117
+ }
118
+ const payload = {
119
+ transaction
120
+ };
121
+ const encrypted = ColumnCrypto.encryptPayload(
122
+ payload,
123
+ this.walletEncryptionPublicKey,
124
+ this.sessionKeyPair.secretKey
125
+ );
126
+ const params = new URLSearchParams({
127
+ request: "signAndSubmitTransaction",
128
+ app_url: this.config.appUrl || "",
129
+ app_name: this.config.appName || "",
130
+ dapp_encryption_public_key: bs582.encode(this.sessionKeyPair.publicKey),
131
+ data: encrypted.data,
132
+ nonce: encrypted.nonce,
133
+ redirect_link: this.config.redirectLink || ""
134
+ });
135
+ if (this.config.appIcon) {
136
+ params.append("app_icon", this.config.appIcon);
137
+ }
138
+ if (this.config.network) {
139
+ params.append("network", this.config.network);
140
+ }
141
+ if (this.config.appDescription) {
142
+ params.append("app_description", this.config.appDescription);
143
+ }
144
+ const scheme = this.config.walletScheme || "column";
145
+ const base = scheme.includes("://") ? scheme : `${scheme}://`;
146
+ return `${base}${base.endsWith("/") ? "" : "/"}?${params.toString()}`;
147
+ }
148
+ /**
149
+ * Step 3: Sign a simple message
150
+ */
151
+ signMessage(message) {
152
+ if (!this.walletEncryptionPublicKey) {
153
+ throw new Error("Wallet not connected.");
154
+ }
155
+ const payload = {
156
+ message
157
+ };
158
+ const encrypted = ColumnCrypto.encryptPayload(
159
+ payload,
160
+ this.walletEncryptionPublicKey,
161
+ this.sessionKeyPair.secretKey
162
+ );
163
+ const params = new URLSearchParams({
164
+ request: "signMessage",
165
+ app_url: this.config.appUrl || "",
166
+ app_name: this.config.appName || "",
167
+ dapp_encryption_public_key: bs582.encode(this.sessionKeyPair.publicKey),
168
+ data: encrypted.data,
169
+ nonce: encrypted.nonce,
170
+ redirect_link: this.config.redirectLink || ""
171
+ });
172
+ if (this.config.appIcon) {
173
+ params.append("app_icon", this.config.appIcon);
174
+ }
175
+ if (this.config.network) {
176
+ params.append("network", this.config.network);
177
+ }
178
+ if (this.config.appDescription) {
179
+ params.append("app_description", this.config.appDescription);
180
+ }
181
+ const scheme = this.config.walletScheme || "column";
182
+ const base = scheme.includes("://") ? scheme : `${scheme}://`;
183
+ return `${base}${base.endsWith("/") ? "" : "/"}?${params.toString()}`;
184
+ }
185
+ /**
186
+ * Utility: Parse the response from Column
187
+ */
188
+ handleResponse(url) {
189
+ let params;
190
+ try {
191
+ const urlObj = new URL(url.includes("://") ? url : `http://localhost/${url}`);
192
+ const hashStr = urlObj.hash.substring(1);
193
+ const searchStr = urlObj.search.substring(1);
194
+ if (hashStr) {
195
+ params = new URLSearchParams(hashStr);
196
+ } else {
197
+ params = new URLSearchParams(searchStr);
198
+ }
199
+ } catch (e) {
200
+ const hashMatch = url.match(/#(.*)$/);
201
+ const queryMatch = url.match(/\?(.*)$/);
202
+ params = new URLSearchParams(hashMatch ? hashMatch[1] : queryMatch ? queryMatch[1] : url);
203
+ }
204
+ const data = params.get("data");
205
+ const nonce = params.get("nonce");
206
+ const error = params.get("error");
207
+ if (error) {
208
+ throw new Error(`Column Wallet Error: ${error}`);
209
+ }
210
+ if (data && nonce && this.walletEncryptionPublicKey) {
211
+ const decrypted = ColumnCrypto.decryptPayload(
212
+ data,
213
+ nonce,
214
+ this.walletEncryptionPublicKey,
215
+ this.sessionKeyPair.secretKey
216
+ );
217
+ if (!decrypted) {
218
+ throw new Error("Column Wallet Error: Decryption failed. The response may have been tampered with or keys do not match.");
219
+ }
220
+ return {
221
+ ...decrypted,
222
+ network: params.get("network")
223
+ // Always include network from URL
224
+ };
225
+ }
226
+ const response = {};
227
+ params.forEach((value, key) => {
228
+ response[key] = value;
229
+ });
230
+ if (response.column_encryption_public_key) {
231
+ this.walletEncryptionPublicKey = response.column_encryption_public_key;
232
+ }
233
+ return response;
234
+ }
235
+ /**
236
+ * Sets the wallet's public key if known from a previous session
237
+ */
238
+ setWalletPublicKey(publicKeyB58) {
239
+ this.walletEncryptionPublicKey = publicKeyB58;
38
240
  }
39
241
  };
40
242
 
@@ -173,7 +375,7 @@ var ColumnConnectModal = class {
173
375
  document.head.appendChild(styleTag);
174
376
  }
175
377
  open() {
176
- if (typeof document === "undefined") return;
378
+ if (typeof document === "undefined" || this.overlay) return;
177
379
  this.overlay = document.createElement("div");
178
380
  this.overlay.className = "column-modal-overlay";
179
381
  this.overlay.innerHTML = `
@@ -220,217 +422,30 @@ var ColumnConnectModal = class {
220
422
  }
221
423
  };
222
424
 
223
- // src/ColumnWalletSDK.ts
224
- var ColumnWalletSDK = class {
225
- config;
226
- sessionKeyPair;
227
- walletEncryptionPublicKey = null;
425
+ // src/ui/ColumnWalletWeb.ts
426
+ var ColumnWalletWeb = class _ColumnWalletWeb extends ColumnWalletSDK {
228
427
  modal;
229
428
  constructor(config) {
230
- this.config = this.autoDetectMetadata(config);
231
- this.sessionKeyPair = ColumnCrypto.generateKeyPair();
429
+ const detectedConfig = _ColumnWalletWeb.autoDetectMetadata(config);
430
+ super(detectedConfig);
232
431
  this.modal = new ColumnConnectModal(() => {
233
432
  window.location.href = this.connect();
234
433
  });
235
434
  }
236
- autoDetectMetadata(config) {
435
+ static autoDetectMetadata(config) {
237
436
  if (typeof document === "undefined") return config;
238
437
  const detectedConfig = { ...config };
239
- if (!detectedConfig.appUrl) {
240
- detectedConfig.appUrl = window.location.origin;
241
- }
242
- if (!detectedConfig.appName) {
243
- detectedConfig.appName = document.title || "Unknown dApp";
244
- }
245
- if (!detectedConfig.appIcon) {
246
- const iconLink = document.querySelector('link[rel~="icon"]') || document.querySelector('link[rel="apple-touch-icon"]');
247
- if (iconLink) {
248
- try {
249
- detectedConfig.appIcon = new URL(iconLink.getAttribute("href") || "", window.location.origin).href;
250
- } catch (e) {
251
- detectedConfig.appIcon = iconLink.href;
252
- }
253
- }
254
- }
255
- if (!detectedConfig.appDescription) {
256
- const metaDescription = document.querySelector('meta[name="description"]') || document.querySelector('meta[property="og:description"]');
257
- if (metaDescription?.content) {
258
- detectedConfig.appDescription = metaDescription.content;
259
- }
260
- }
261
- if (!detectedConfig.redirectLink) {
262
- detectedConfig.redirectLink = window.location.href.split("?")[0];
263
- }
438
+ if (!detectedConfig.appUrl) detectedConfig.appUrl = window.location.origin;
439
+ if (!detectedConfig.appName) detectedConfig.appName = document.title || "Unknown dApp";
440
+ if (!detectedConfig.redirectLink) detectedConfig.redirectLink = window.location.href.split("?")[0];
264
441
  return detectedConfig;
265
442
  }
266
- /**
267
- * Opens the premium Column selection modal
268
- */
269
443
  openConnectModal() {
270
444
  this.modal.open();
271
445
  }
272
- setWalletEncryptionPublicKey(key) {
273
- this.walletEncryptionPublicKey = key;
274
- }
275
- /**
276
- * Alias for setWalletEncryptionPublicKey to match docs
277
- */
278
- importWalletKey(key) {
279
- this.setWalletEncryptionPublicKey(key);
280
- }
281
- /**
282
- * Step 1: Connect to the wallet
283
- */
284
- connect() {
285
- const params = new URLSearchParams({
286
- request: "connect",
287
- app_url: this.config.appUrl || "",
288
- app_name: this.config.appName || "",
289
- dapp_encryption_public_key: bs582.encode(this.sessionKeyPair.publicKey),
290
- redirect_link: this.config.redirectLink || ""
291
- });
292
- if (this.config.appIcon) {
293
- params.append("app_icon", this.config.appIcon);
294
- }
295
- if (this.config.network) {
296
- params.append("network", this.config.network);
297
- }
298
- if (this.config.appDescription) {
299
- params.append("app_description", this.config.appDescription);
300
- }
301
- const scheme = this.config.walletScheme || "column";
302
- const base = scheme.includes("://") ? scheme : `${scheme}://`;
303
- return `${base}${base.endsWith("/") ? "" : "/"}?${params.toString()}`;
304
- }
305
- /**
306
- * Step 2: Sign and Submit a transaction
307
- */
308
- signAndSubmitTransaction(transaction) {
309
- if (!this.walletEncryptionPublicKey) {
310
- throw new Error("Wallet not connected. Call connect() first and store the wallet_encryption_public_key.");
311
- }
312
- const payload = {
313
- transaction
314
- };
315
- const encrypted = ColumnCrypto.encryptPayload(
316
- payload,
317
- this.walletEncryptionPublicKey,
318
- this.sessionKeyPair.secretKey
319
- );
320
- const params = new URLSearchParams({
321
- request: "signAndSubmitTransaction",
322
- app_url: this.config.appUrl || "",
323
- app_name: this.config.appName || "",
324
- dapp_encryption_public_key: bs582.encode(this.sessionKeyPair.publicKey),
325
- data: encrypted.data,
326
- nonce: encrypted.nonce,
327
- redirect_link: this.config.redirectLink || ""
328
- });
329
- if (this.config.appIcon) {
330
- params.append("app_icon", this.config.appIcon);
331
- }
332
- if (this.config.network) {
333
- params.append("network", this.config.network);
334
- }
335
- if (this.config.appDescription) {
336
- params.append("app_description", this.config.appDescription);
337
- }
338
- const scheme = this.config.walletScheme || "column";
339
- const base = scheme.includes("://") ? scheme : `${scheme}://`;
340
- return `${base}${base.endsWith("/") ? "" : "/"}?${params.toString()}`;
341
- }
342
- /**
343
- * Step 3: Sign a simple message
344
- */
345
- signMessage(message) {
346
- if (!this.walletEncryptionPublicKey) {
347
- throw new Error("Wallet not connected.");
348
- }
349
- const payload = {
350
- message
351
- };
352
- const encrypted = ColumnCrypto.encryptPayload(
353
- payload,
354
- this.walletEncryptionPublicKey,
355
- this.sessionKeyPair.secretKey
356
- );
357
- const params = new URLSearchParams({
358
- request: "signMessage",
359
- app_url: this.config.appUrl || "",
360
- app_name: this.config.appName || "",
361
- dapp_encryption_public_key: bs582.encode(this.sessionKeyPair.publicKey),
362
- data: encrypted.data,
363
- nonce: encrypted.nonce,
364
- redirect_link: this.config.redirectLink || ""
365
- });
366
- if (this.config.appIcon) {
367
- params.append("app_icon", this.config.appIcon);
368
- }
369
- if (this.config.network) {
370
- params.append("network", this.config.network);
371
- }
372
- if (this.config.appDescription) {
373
- params.append("app_description", this.config.appDescription);
374
- }
375
- const scheme = this.config.walletScheme || "column";
376
- const base = scheme.includes("://") ? scheme : `${scheme}://`;
377
- return `${base}${base.endsWith("/") ? "" : "/"}?${params.toString()}`;
378
- }
379
- /**
380
- * Utility: Parse the response from Column
381
- */
382
- handleResponse(url) {
383
- let params;
384
- try {
385
- const urlObj = new URL(url.includes("://") ? url : `http://localhost/${url}`);
386
- const hashStr = urlObj.hash.substring(1);
387
- const searchStr = urlObj.search.substring(1);
388
- if (hashStr) {
389
- params = new URLSearchParams(hashStr);
390
- } else {
391
- params = new URLSearchParams(searchStr);
392
- }
393
- } catch (e) {
394
- const hashMatch = url.match(/#(.*)$/);
395
- const queryMatch = url.match(/\?(.*)$/);
396
- params = new URLSearchParams(hashMatch ? hashMatch[1] : queryMatch ? queryMatch[1] : url);
397
- }
398
- const data = params.get("data");
399
- const nonce = params.get("nonce");
400
- const error = params.get("error");
401
- if (error) {
402
- throw new Error(`Column Wallet Error: ${error}`);
403
- }
404
- if (data && nonce && this.walletEncryptionPublicKey) {
405
- const decrypted = ColumnCrypto.decryptPayload(
406
- data,
407
- nonce,
408
- this.walletEncryptionPublicKey,
409
- this.sessionKeyPair.secretKey
410
- );
411
- return {
412
- ...decrypted,
413
- network: params.get("network")
414
- // Always include network from URL
415
- };
416
- }
417
- const response = {};
418
- params.forEach((value, key) => {
419
- response[key] = value;
420
- });
421
- if (response.column_encryption_public_key) {
422
- this.walletEncryptionPublicKey = response.column_encryption_public_key;
423
- }
424
- return response;
425
- }
426
- /**
427
- * Sets the wallet's public key if known from a previous session
428
- */
429
- setWalletPublicKey(publicKeyB58) {
430
- this.walletEncryptionPublicKey = publicKeyB58;
431
- }
432
446
  };
433
447
  export {
434
448
  ColumnCrypto,
435
- ColumnWalletSDK
449
+ ColumnWalletSDK,
450
+ ColumnWalletWeb
436
451
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@column-org/wallet-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Column Wallet Mobile Deep-Link SDK for Movement/Aptos ecosystem",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",