@cartridge/controller 0.7.7 → 0.7.8

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.
Files changed (39) hide show
  1. package/.turbo/turbo-build$colon$deps.log +23 -23
  2. package/.turbo/turbo-build.log +31 -31
  3. package/dist/controller.cjs +472 -3
  4. package/dist/controller.cjs.map +1 -1
  5. package/dist/controller.d.cts +1 -1
  6. package/dist/controller.d.ts +1 -1
  7. package/dist/controller.js +472 -3
  8. package/dist/controller.js.map +1 -1
  9. package/dist/index.cjs +1908 -1214
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +46 -3
  12. package/dist/index.d.ts +46 -3
  13. package/dist/index.js +1905 -1215
  14. package/dist/index.js.map +1 -1
  15. package/dist/node/index.cjs +1 -1
  16. package/dist/node/index.cjs.map +1 -1
  17. package/dist/node/index.d.cts +2 -2
  18. package/dist/node/index.d.ts +2 -2
  19. package/dist/node/index.js +1 -1
  20. package/dist/node/index.js.map +1 -1
  21. package/dist/{provider-CTDncg8U.d.cts → provider-BeCgS86X.d.cts} +64 -1
  22. package/dist/{provider-CTDncg8U.d.ts → provider-BeCgS86X.d.ts} +64 -1
  23. package/dist/session/index.cjs +1 -1
  24. package/dist/session/index.cjs.map +1 -1
  25. package/dist/session/index.d.cts +2 -2
  26. package/dist/session/index.d.ts +2 -2
  27. package/dist/session/index.js +1 -1
  28. package/dist/session/index.js.map +1 -1
  29. package/package.json +8 -5
  30. package/src/iframe/base.ts +1 -1
  31. package/src/iframe/keychain.ts +11 -0
  32. package/src/index.ts +1 -0
  33. package/src/types.ts +24 -0
  34. package/src/wallets/argent/index.ts +122 -0
  35. package/src/wallets/bridge.ts +165 -0
  36. package/src/wallets/index.ts +5 -0
  37. package/src/wallets/metamask/index.ts +210 -0
  38. package/src/wallets/phantom/index.ts +124 -0
  39. package/src/wallets/types.ts +32 -0
@@ -1,5 +1,8 @@
1
1
  import { shortString, WalletAccount, constants, Provider } from 'starknet';
2
2
  import { connectToChild } from '@cartridge/penpal';
3
+ import { MetaMaskSDK } from '@metamask/sdk';
4
+ import { connect } from 'starknetkit';
5
+ import { InjectedConnector } from 'starknetkit/injected';
3
6
  import { Permission } from '@starknet-io/types-js';
4
7
 
5
8
  // src/account.ts
@@ -174,7 +177,7 @@ var IFrame = class {
174
177
  this.container = container;
175
178
  connectToChild({
176
179
  iframe: this.iframe,
177
- methods: { close: () => this.close(), ...methods }
180
+ methods: { close: (_origin) => () => this.close(), ...methods }
178
181
  }).promise.then(onConnect);
179
182
  this.resize();
180
183
  window.addEventListener("resize", () => this.resize());
@@ -238,11 +241,472 @@ var IFrame = class {
238
241
  // src/constants.ts
239
242
  var KEYCHAIN_URL = "https://x.cartridge.gg";
240
243
  var PROFILE_URL = "https://profile.cartridge.gg";
244
+ var MetaMaskWallet = class {
245
+ type = "metamask";
246
+ platform = "ethereum";
247
+ MMSDK;
248
+ account = void 0;
249
+ constructor() {
250
+ this.MMSDK = new MetaMaskSDK({
251
+ dappMetadata: {
252
+ name: "Cartridge Controller",
253
+ url: window.location.href
254
+ }
255
+ });
256
+ }
257
+ isAvailable() {
258
+ return typeof window !== "undefined" && !!window.ethereum?.isMetaMask;
259
+ }
260
+ getInfo() {
261
+ const available = this.isAvailable();
262
+ return {
263
+ type: this.type,
264
+ available,
265
+ version: available ? window.ethereum?.version || "Unknown" : void 0,
266
+ chainId: available ? window.ethereum?.chainId : void 0,
267
+ name: "MetaMask",
268
+ platform: this.platform
269
+ };
270
+ }
271
+ async connect() {
272
+ if (this.account) {
273
+ return { success: true, wallet: this.type, account: this.account };
274
+ }
275
+ try {
276
+ if (!this.isAvailable()) {
277
+ throw new Error("MetaMask is not available");
278
+ }
279
+ const accounts = await this.MMSDK.connect();
280
+ if (accounts && accounts.length > 0) {
281
+ this.account = accounts[0];
282
+ return { success: true, wallet: this.type, account: this.account };
283
+ }
284
+ throw new Error("No accounts found");
285
+ } catch (error) {
286
+ console.error(`Error connecting to MetaMask:`, error);
287
+ return {
288
+ success: false,
289
+ wallet: this.type,
290
+ error: error.message || "Unknown error"
291
+ };
292
+ }
293
+ }
294
+ async signTransaction(transaction) {
295
+ try {
296
+ if (!this.isAvailable() || !this.account) {
297
+ throw new Error("MetaMask is not connected");
298
+ }
299
+ const ethereum = this.MMSDK.getProvider();
300
+ if (!ethereum) {
301
+ throw new Error("MetaMask is not connected");
302
+ }
303
+ const result = await ethereum.request({
304
+ method: "eth_sendTransaction",
305
+ params: [transaction]
306
+ });
307
+ return { success: true, wallet: this.type, result };
308
+ } catch (error) {
309
+ console.error(`Error signing transaction with MetaMask:`, error);
310
+ return {
311
+ success: false,
312
+ wallet: this.type,
313
+ error: error.message || "Unknown error"
314
+ };
315
+ }
316
+ }
317
+ async signMessage(message) {
318
+ try {
319
+ if (!this.isAvailable() || !this.account) {
320
+ throw new Error("MetaMask is not connected");
321
+ }
322
+ const result = await this.MMSDK.connectAndSign({
323
+ msg: message
324
+ });
325
+ return { success: true, wallet: this.type, result };
326
+ } catch (error) {
327
+ console.error(`Error signing message with MetaMask:`, error);
328
+ return {
329
+ success: false,
330
+ wallet: this.type,
331
+ error: error.message || "Unknown error"
332
+ };
333
+ }
334
+ }
335
+ async signTypedData(data) {
336
+ try {
337
+ if (!this.isAvailable() || !this.account) {
338
+ throw new Error("MetaMask is not connected");
339
+ }
340
+ const ethereum = this.MMSDK.getProvider();
341
+ if (!ethereum) {
342
+ throw new Error("MetaMask is not connected");
343
+ }
344
+ const result = await ethereum.request({
345
+ method: "eth_signTypedData_v4",
346
+ params: [this.account, JSON.stringify(data)]
347
+ });
348
+ return { success: true, wallet: this.type, result };
349
+ } catch (error) {
350
+ console.error(`Error signing typed data with MetaMask:`, error);
351
+ return {
352
+ success: false,
353
+ wallet: this.type,
354
+ error: error.message || "Unknown error"
355
+ };
356
+ }
357
+ }
358
+ async switchChain(chainId) {
359
+ try {
360
+ if (!this.isAvailable()) {
361
+ throw new Error("MetaMask is not available");
362
+ }
363
+ const ethereum = this.MMSDK.getProvider();
364
+ if (!ethereum) {
365
+ throw new Error("MetaMask is not connected");
366
+ }
367
+ try {
368
+ await ethereum.request({
369
+ method: "wallet_switchEthereumChain",
370
+ params: [{ chainId }]
371
+ });
372
+ return true;
373
+ } catch (error) {
374
+ if (error.code === 4902) {
375
+ console.warn("Chain not added to MetaMask");
376
+ }
377
+ throw error;
378
+ }
379
+ } catch (error) {
380
+ console.error(`Error switching chain for MetaMask:`, error);
381
+ return false;
382
+ }
383
+ }
384
+ async getBalance(tokenAddress) {
385
+ try {
386
+ if (!this.isAvailable() || !this.account) {
387
+ throw new Error("MetaMask is not connected");
388
+ }
389
+ if (tokenAddress) {
390
+ return {
391
+ success: false,
392
+ wallet: this.type,
393
+ error: "Not implemented for ERC20"
394
+ };
395
+ } else {
396
+ const ethereum = this.MMSDK.getProvider();
397
+ if (!ethereum) {
398
+ throw new Error("MetaMask is not connected");
399
+ }
400
+ const balance = await ethereum.request({
401
+ method: "eth_getBalance",
402
+ params: [this.account, "latest"]
403
+ });
404
+ return { success: true, wallet: this.type, result: balance };
405
+ }
406
+ } catch (error) {
407
+ console.error(`Error getting balance from MetaMask:`, error);
408
+ return {
409
+ success: false,
410
+ wallet: this.type,
411
+ error: error.message || "Unknown error"
412
+ };
413
+ }
414
+ }
415
+ };
416
+
417
+ // src/wallets/phantom/index.ts
418
+ var PhantomWallet = class {
419
+ type = "phantom";
420
+ platform = "solana";
421
+ account = void 0;
422
+ isAvailable() {
423
+ return typeof window !== "undefined" && !!window.solana?.isPhantom;
424
+ }
425
+ getInfo() {
426
+ const available = this.isAvailable();
427
+ return {
428
+ type: this.type,
429
+ available,
430
+ version: "Unknown",
431
+ name: "Phantom",
432
+ platform: this.platform
433
+ };
434
+ }
435
+ async connect() {
436
+ if (this.account) {
437
+ return { success: true, wallet: this.type, account: this.account };
438
+ }
439
+ try {
440
+ if (!this.isAvailable()) {
441
+ throw new Error("Phantom is not available");
442
+ }
443
+ const response = await window.solana.connect();
444
+ if (response.publicKey) {
445
+ this.account = response.publicKey.toString();
446
+ return { success: true, wallet: this.type, account: this.account };
447
+ }
448
+ throw new Error("No accounts found");
449
+ } catch (error) {
450
+ console.error(`Error connecting to Phantom:`, error);
451
+ return {
452
+ success: false,
453
+ wallet: this.type,
454
+ error: error.message || "Unknown error"
455
+ };
456
+ }
457
+ }
458
+ async signTransaction(transaction) {
459
+ try {
460
+ if (!this.isAvailable() || !this.account) {
461
+ throw new Error("Phantom is not connected");
462
+ }
463
+ const result = await window.solana.signTransaction(transaction);
464
+ return { success: true, wallet: this.type, result };
465
+ } catch (error) {
466
+ console.error(`Error signing transaction with Phantom:`, error);
467
+ return {
468
+ success: false,
469
+ wallet: this.type,
470
+ error: error.message || "Unknown error"
471
+ };
472
+ }
473
+ }
474
+ async signMessage(message) {
475
+ try {
476
+ if (!this.isAvailable() || !this.account) {
477
+ throw new Error("Phantom is not connected");
478
+ }
479
+ const encodedMessage = new TextEncoder().encode(message);
480
+ const result = await window.solana.signMessage(encodedMessage, "utf8");
481
+ return { success: true, wallet: this.type, result };
482
+ } catch (error) {
483
+ console.error(`Error signing message with Phantom:`, error);
484
+ return {
485
+ success: false,
486
+ wallet: this.type,
487
+ error: error.message || "Unknown error"
488
+ };
489
+ }
490
+ }
491
+ async switchChain(_chainId) {
492
+ console.warn("Chain switching not supported for Phantom");
493
+ return false;
494
+ }
495
+ async getBalance(_tokenAddress) {
496
+ try {
497
+ if (!this.isAvailable() || !this.account) {
498
+ throw new Error("Phantom is not connected");
499
+ }
500
+ return {
501
+ success: true,
502
+ wallet: this.type,
503
+ result: "Implement based on Phantom API"
504
+ };
505
+ } catch (error) {
506
+ console.error(`Error getting balance from Phantom:`, error);
507
+ return {
508
+ success: false,
509
+ wallet: this.type,
510
+ error: error.message || "Unknown error"
511
+ };
512
+ }
513
+ }
514
+ };
515
+ var ArgentWallet = class {
516
+ type = "argent";
517
+ platform = "starknet";
518
+ wallet = void 0;
519
+ account = void 0;
520
+ isAvailable() {
521
+ return typeof window !== "undefined" && !!window.starknet_argentX;
522
+ }
523
+ getInfo() {
524
+ const available = this.isAvailable();
525
+ return {
526
+ type: this.type,
527
+ available,
528
+ version: available ? window.starknet_argentX?.version || "Unknown" : void 0,
529
+ chainId: available ? window.starknet_argentX?.chainId : void 0,
530
+ name: "Argent",
531
+ platform: this.platform
532
+ };
533
+ }
534
+ async connect() {
535
+ if (this.account) {
536
+ return { success: true, wallet: this.type, account: this.account };
537
+ }
538
+ try {
539
+ if (!this.isAvailable()) {
540
+ throw new Error("Argent is not available");
541
+ }
542
+ const { wallet, connectorData } = await connect({
543
+ connectors: [new InjectedConnector({ options: { id: "argentX" } })]
544
+ });
545
+ if (!wallet) {
546
+ throw new Error("No wallet found");
547
+ }
548
+ this.wallet = wallet;
549
+ this.account = connectorData?.account;
550
+ return { success: true, wallet: this.type, account: this.account };
551
+ } catch (error) {
552
+ console.error(`Error connecting to Argent:`, error);
553
+ return {
554
+ success: false,
555
+ wallet: this.type,
556
+ error: error.message || "Unknown error"
557
+ };
558
+ }
559
+ }
560
+ async signTypedData(data) {
561
+ try {
562
+ if (!this.isAvailable() || !this.wallet) {
563
+ throw new Error("Argent is not connected");
564
+ }
565
+ console.log("signTypedData", data);
566
+ const sig = await this.wallet.request({
567
+ type: "wallet_signTypedData",
568
+ params: data
569
+ });
570
+ return { success: true, wallet: this.type, result: sig };
571
+ } catch (error) {
572
+ console.error(`Error signing typed data with Argent:`, error);
573
+ return {
574
+ success: false,
575
+ wallet: this.type,
576
+ error: error.message || "Unknown error"
577
+ };
578
+ }
579
+ }
580
+ async switchChain(_chainId) {
581
+ console.warn(
582
+ "Chain switching for Argent may require custom implementation"
583
+ );
584
+ return false;
585
+ }
586
+ async getBalance(_tokenAddress) {
587
+ try {
588
+ if (!this.isAvailable() || !this.wallet) {
589
+ throw new Error("Argent is not connected");
590
+ }
591
+ return {
592
+ success: true,
593
+ wallet: this.type,
594
+ result: "Implement based on Argent API"
595
+ };
596
+ } catch (error) {
597
+ console.error(`Error getting balance from Argent:`, error);
598
+ return {
599
+ success: false,
600
+ wallet: this.type,
601
+ error: error.message || "Unknown error"
602
+ };
603
+ }
604
+ }
605
+ };
606
+
607
+ // src/wallets/bridge.ts
608
+ var WalletBridge = class {
609
+ walletAdapters;
610
+ connectedWallets = /* @__PURE__ */ new Map();
611
+ constructor() {
612
+ this.walletAdapters = /* @__PURE__ */ new Map();
613
+ this.walletAdapters.set("metamask", new MetaMaskWallet());
614
+ this.walletAdapters.set("phantom", new PhantomWallet());
615
+ this.walletAdapters.set("argent", new ArgentWallet());
616
+ if (typeof window !== "undefined") {
617
+ window.wallet_bridge = this;
618
+ }
619
+ }
620
+ getIFrameMethods() {
621
+ return {
622
+ externalDetectWallets: (_origin) => () => this.detectWallets(),
623
+ externalConnectWallet: (_origin) => (type) => this.connectWallet(type),
624
+ externalSignMessage: (_origin) => (type, message) => this.signMessage(type, message),
625
+ externalSignTypedData: (_origin) => (type, data) => this.signTypedData(type, data),
626
+ externalGetBalance: (_origin) => (type, tokenAddress) => this.getBalance(type, tokenAddress)
627
+ };
628
+ }
629
+ async detectWallets() {
630
+ const wallets = Array.from(this.walletAdapters.values()).map(
631
+ (adapter) => adapter.getInfo()
632
+ );
633
+ return wallets;
634
+ }
635
+ getWalletAdapter(type) {
636
+ const adapter = this.walletAdapters.get(type);
637
+ if (!adapter) {
638
+ throw new Error(`Unsupported wallet type: ${type}`);
639
+ }
640
+ return adapter;
641
+ }
642
+ handleError(type, error, operation) {
643
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
644
+ console.error(`Error ${operation} with ${type} wallet:`, error);
645
+ return { success: false, wallet: type, error: errorMessage };
646
+ }
647
+ async connectWallet(type) {
648
+ try {
649
+ if (this.connectedWallets.has(type)) {
650
+ const wallet2 = this.connectedWallets.get(type);
651
+ return { success: true, wallet: type, account: wallet2.type };
652
+ }
653
+ const wallet = this.getWalletAdapter(type);
654
+ const response = await wallet.connect();
655
+ if (response.success) {
656
+ this.connectedWallets.set(type, wallet);
657
+ }
658
+ return response;
659
+ } catch (error) {
660
+ return this.handleError(type, error, "connecting to");
661
+ }
662
+ }
663
+ async signMessage(type, message) {
664
+ try {
665
+ if (!this.connectedWallets.has(type)) {
666
+ throw new Error(`Wallet ${type} is not connected`);
667
+ }
668
+ const wallet = this.connectedWallets.get(type);
669
+ if (!wallet.signMessage) {
670
+ throw new Error(`Wallet ${type} does not support signing messages`);
671
+ }
672
+ return await wallet.signMessage(message);
673
+ } catch (error) {
674
+ return this.handleError(type, error, "signing message with");
675
+ }
676
+ }
677
+ async signTypedData(type, data) {
678
+ try {
679
+ if (!this.connectedWallets.has(type)) {
680
+ throw new Error(`Wallet ${type} is not connected`);
681
+ }
682
+ const wallet = this.connectedWallets.get(type);
683
+ if (!wallet.signTypedData) {
684
+ throw new Error(`Wallet ${type} does not support signing typed data`);
685
+ }
686
+ return await wallet.signTypedData(data);
687
+ } catch (error) {
688
+ return this.handleError(type, error, "signing typed data with");
689
+ }
690
+ }
691
+ async getBalance(type, tokenAddress) {
692
+ try {
693
+ if (!this.connectedWallets.has(type)) {
694
+ throw new Error(`Wallet ${type} is not connected`);
695
+ }
696
+ const wallet = this.connectedWallets.get(type);
697
+ return await wallet.getBalance(tokenAddress);
698
+ } catch (error) {
699
+ return this.handleError(type, error, "getting balance from");
700
+ }
701
+ }
702
+ };
241
703
 
242
704
  // src/iframe/keychain.ts
243
705
  var KeychainIFrame = class extends IFrame {
706
+ walletBridge;
244
707
  constructor({ url, policies, ...iframeOptions }) {
245
708
  const _url = new URL(url ?? KEYCHAIN_URL);
709
+ const walletBridge = new WalletBridge();
246
710
  if (policies) {
247
711
  _url.searchParams.set(
248
712
  "policies",
@@ -252,8 +716,13 @@ var KeychainIFrame = class extends IFrame {
252
716
  super({
253
717
  ...iframeOptions,
254
718
  id: "controller-keychain",
255
- url: _url
719
+ url: _url,
720
+ methods: walletBridge.getIFrameMethods()
256
721
  });
722
+ this.walletBridge = walletBridge;
723
+ }
724
+ getWalletBridge() {
725
+ return this.walletBridge;
257
726
  }
258
727
  };
259
728
 
@@ -315,7 +784,7 @@ var NotReadyToConnect = class _NotReadyToConnect extends Error {
315
784
 
316
785
  // package.json
317
786
  var package_default = {
318
- version: "0.7.7"};
787
+ version: "0.7.8"};
319
788
 
320
789
  // src/icon.ts
321
790
  var icon = "data:image/png;base64,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";