@cartridge/controller 0.7.7 → 0.7.9-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/.turbo/turbo-build$colon$deps.log +49 -59
  2. package/.turbo/turbo-build.log +45 -63
  3. package/dist/account.d.ts +35 -0
  4. package/dist/constants.d.ts +3 -0
  5. package/dist/controller.d.ts +3 -6
  6. package/dist/errors.d.ts +3 -0
  7. package/dist/icon.d.ts +1 -0
  8. package/dist/iframe/base.d.ts +26 -0
  9. package/dist/iframe/index.d.ts +3 -0
  10. package/dist/iframe/keychain.d.ts +10 -0
  11. package/dist/iframe/profile.d.ts +12 -0
  12. package/dist/index.d.ts +6 -24
  13. package/dist/index.js +2649 -1934
  14. package/dist/index.js.map +1 -1
  15. package/dist/lookup.d.ts +2 -4
  16. package/dist/mutex.d.ts +12 -0
  17. package/dist/node/index.cjs +1 -12
  18. package/dist/node/index.cjs.map +1 -1
  19. package/dist/node/index.d.cts +93 -8
  20. package/dist/node/index.d.ts +93 -8
  21. package/dist/node/index.js +2 -12
  22. package/dist/node/index.js.map +1 -1
  23. package/dist/policies.d.ts +15 -0
  24. package/dist/provider-qJi60GEX.js +286 -0
  25. package/dist/provider-qJi60GEX.js.map +1 -0
  26. package/dist/provider.d.ts +21 -0
  27. package/dist/session/account.d.ts +31 -0
  28. package/dist/session/backend.d.ts +58 -0
  29. package/dist/session/index.d.ts +4 -38
  30. package/dist/session/{index.d.cts → provider.d.ts} +4 -10
  31. package/dist/session.d.ts +6 -0
  32. package/dist/session.js +354 -0
  33. package/dist/session.js.map +1 -0
  34. package/dist/stats.html +4949 -0
  35. package/dist/telegram/backend.d.ts +30 -0
  36. package/dist/telegram/provider.d.ts +24 -0
  37. package/dist/types.d.ts +146 -0
  38. package/dist/utils.d.ts +15 -0
  39. package/dist/wallets/argent/index.d.ts +14 -0
  40. package/dist/wallets/bridge.d.ts +29 -0
  41. package/dist/wallets/index.d.ts +5 -0
  42. package/dist/wallets/metamask/index.d.ts +16 -0
  43. package/dist/wallets/phantom/index.d.ts +13 -0
  44. package/dist/wallets/types.d.ts +27 -0
  45. package/package.json +21 -41
  46. package/src/iframe/base.ts +1 -1
  47. package/src/iframe/keychain.ts +11 -0
  48. package/src/iframe/profile.ts +9 -7
  49. package/src/index.ts +1 -0
  50. package/src/node/index.ts +1 -1
  51. package/src/types.ts +24 -0
  52. package/src/wallets/argent/index.ts +122 -0
  53. package/src/wallets/bridge.ts +165 -0
  54. package/src/wallets/index.ts +5 -0
  55. package/src/wallets/metamask/index.ts +210 -0
  56. package/src/wallets/phantom/index.ts +124 -0
  57. package/src/wallets/types.ts +32 -0
  58. package/tsup.node.config.ts +15 -0
  59. package/vite.config.js +83 -0
  60. package/dist/controller.cjs +0 -803
  61. package/dist/controller.cjs.map +0 -1
  62. package/dist/controller.d.cts +0 -34
  63. package/dist/controller.js +0 -801
  64. package/dist/controller.js.map +0 -1
  65. package/dist/index.cjs +0 -2695
  66. package/dist/index.cjs.map +0 -1
  67. package/dist/index.d.cts +0 -25
  68. package/dist/lookup.cjs +0 -59
  69. package/dist/lookup.cjs.map +0 -1
  70. package/dist/lookup.d.cts +0 -4
  71. package/dist/lookup.js +0 -56
  72. package/dist/lookup.js.map +0 -1
  73. package/dist/policies-DD1aPjQ4.d.cts +0 -21
  74. package/dist/policies-DD1aPjQ4.d.ts +0 -21
  75. package/dist/provider-CTDncg8U.d.cts +0 -203
  76. package/dist/provider-CTDncg8U.d.ts +0 -203
  77. package/dist/session/index.cjs +0 -484
  78. package/dist/session/index.cjs.map +0 -1
  79. package/dist/session/index.js +0 -478
  80. package/dist/session/index.js.map +0 -1
@@ -0,0 +1,30 @@
1
+ import { UnifiedBackend } from '../session/backend';
2
+ /**
3
+ * Implements the UnifiedBackend interface for Telegram storage operations.
4
+ */
5
+ export declare class TelegramBackend implements UnifiedBackend {
6
+ /**
7
+ * Retrieves the value associated with the specified key from Telegram cloud storage.
8
+ * @param key - The key to look up in the storage.
9
+ * @returns A promise that resolves to the stored value as a string, or null if the key doesn't exist.
10
+ */
11
+ get(key: string): Promise<string | null>;
12
+ /**
13
+ * Stores a key-value pair in Telegram cloud storage.
14
+ * @param key - The key under which to store the value.
15
+ * @param value - The value to be stored.
16
+ * @returns A promise that resolves when the value has been successfully stored.
17
+ */
18
+ set(key: string, value: string): Promise<void>;
19
+ /**
20
+ * Removes the key-value pair associated with the specified key from Telegram cloud storage.
21
+ * @param key - The key of the item to be removed.
22
+ * @returns A promise that resolves when the item has been successfully removed.
23
+ */
24
+ delete(key: string): Promise<void>;
25
+ /**
26
+ * Opens the specified URL using Telegram's openLink function.
27
+ * @param url - The URL to open.
28
+ */
29
+ openLink(url: string): void;
30
+ }
@@ -0,0 +1,24 @@
1
+ import { WalletAccount } from 'starknet';
2
+ import { default as BaseProvider } from '../provider';
3
+ import { SessionPolicies } from '@cartridge/presets';
4
+ import { AddStarknetChainParameters } from '@starknet-io/types-js';
5
+ import { ParsedSessionPolicies } from '../policies';
6
+ export default class TelegramProvider extends BaseProvider {
7
+ private _tmaUrl;
8
+ protected _chainId: string;
9
+ protected _username?: string;
10
+ protected _policies: ParsedSessionPolicies;
11
+ private _rpcUrl;
12
+ constructor({ rpc, chainId, policies, tmaUrl, }: {
13
+ rpc: string;
14
+ chainId: string;
15
+ policies: SessionPolicies;
16
+ tmaUrl: string;
17
+ });
18
+ probe(): Promise<WalletAccount | undefined>;
19
+ connect(): Promise<WalletAccount | undefined>;
20
+ switchStarknetChain(_chainId: string): Promise<boolean>;
21
+ addStarknetChain(_chain: AddStarknetChainParameters): Promise<boolean>;
22
+ disconnect(): Promise<void>;
23
+ tryRetrieveFromQueryOrStorage(): Promise<WalletAccount | undefined>;
24
+ }
@@ -0,0 +1,146 @@
1
+ import { constants, BigNumberish, Call, Abi, InvocationsDetails } from 'starknet';
2
+ import { AddInvokeTransactionResult, ChainId, Signature, TypedData } from '@starknet-io/types-js';
3
+ import { KeychainIFrame, ProfileIFrame } from './iframe';
4
+ import { Policy, SessionPolicies } from '@cartridge/presets';
5
+ import { ExternalWallet, ExternalWalletResponse, ExternalWalletType } from './wallets/types';
6
+ export type Session = {
7
+ chainId: constants.StarknetChainId;
8
+ policies: Policy[];
9
+ maxFee: BigNumberish;
10
+ expiresAt: bigint;
11
+ credentials: {
12
+ authorization: string[];
13
+ privateKey: string;
14
+ };
15
+ };
16
+ export declare enum ResponseCodes {
17
+ SUCCESS = "SUCCESS",
18
+ NOT_CONNECTED = "NOT_CONNECTED",
19
+ ERROR = "ERROR",
20
+ CANCELED = "CANCELED",
21
+ USER_INTERACTION_REQUIRED = "USER_INTERACTION_REQUIRED"
22
+ }
23
+ export type ConnectError = {
24
+ code: ResponseCodes;
25
+ message: string;
26
+ error?: ControllerError;
27
+ };
28
+ export type ControllerError = {
29
+ code: Number;
30
+ message: string;
31
+ data?: any;
32
+ };
33
+ export type ConnectReply = {
34
+ code: ResponseCodes.SUCCESS;
35
+ address: string;
36
+ policies?: SessionPolicies;
37
+ };
38
+ export type ExecuteReply = (AddInvokeTransactionResult & {
39
+ code: ResponseCodes.SUCCESS;
40
+ }) | {
41
+ code: ResponseCodes.USER_INTERACTION_REQUIRED;
42
+ };
43
+ export type ProbeReply = {
44
+ code: ResponseCodes.SUCCESS;
45
+ address: string;
46
+ rpcUrl?: string;
47
+ };
48
+ export type DeployReply = {
49
+ code: ResponseCodes.SUCCESS;
50
+ transaction_hash: string;
51
+ };
52
+ export type IFrames = {
53
+ keychain: KeychainIFrame;
54
+ profile?: ProfileIFrame;
55
+ version?: number;
56
+ };
57
+ export interface LookupRequest {
58
+ usernames?: string[];
59
+ addresses?: string[];
60
+ }
61
+ export interface LookupResult {
62
+ username: string;
63
+ addresses: string[];
64
+ }
65
+ export interface LookupResponse {
66
+ results: LookupResult[];
67
+ }
68
+ type ContractAddress = string;
69
+ type CartridgeID = string;
70
+ export type ControllerAccounts = Record<ContractAddress, CartridgeID>;
71
+ export interface Keychain {
72
+ probe(rpcUrl: string): Promise<ProbeReply | ConnectError>;
73
+ connect(policies: SessionPolicies, rpcUrl: string): Promise<ConnectReply | ConnectError>;
74
+ disconnect(): void;
75
+ reset(): void;
76
+ revoke(origin: string): void;
77
+ deploy(): Promise<DeployReply | ConnectError>;
78
+ execute(calls: Call | Call[], abis?: Abi[], transactionsDetail?: InvocationsDetails, sync?: boolean, paymaster?: any, error?: ControllerError): Promise<ExecuteReply | ConnectError>;
79
+ signMessage(typedData: TypedData, account: string, async?: boolean): Promise<Signature | ConnectError>;
80
+ openSettings(): Promise<void | ConnectError>;
81
+ session(): Promise<Session>;
82
+ sessions(): Promise<{
83
+ [key: string]: Session;
84
+ }>;
85
+ delegateAccount(): string;
86
+ username(): string;
87
+ openPurchaseCredits(): void;
88
+ openExecute(calls: Call[]): Promise<void>;
89
+ switchChain(rpcUrl: string): Promise<void>;
90
+ externalDetectWallets(): Promise<ExternalWallet[]>;
91
+ externalConnectWallet(type: ExternalWalletType): Promise<ExternalWalletResponse>;
92
+ externalSignMessage(type: ExternalWalletType, message: string): Promise<ExternalWalletResponse>;
93
+ externalSignTypedData(type: ExternalWalletType, data: any): Promise<ExternalWalletResponse>;
94
+ externalGetBalance(type: ExternalWalletType, tokenAddress?: string): Promise<ExternalWalletResponse>;
95
+ }
96
+ export interface Profile {
97
+ navigate(path: string): void;
98
+ switchChain(rpcUrl: string): Promise<void>;
99
+ }
100
+ export interface Modal {
101
+ open: () => void;
102
+ close: () => void;
103
+ }
104
+ /**
105
+ * Options for configuring the controller
106
+ */
107
+ export type ControllerOptions = ProviderOptions & KeychainOptions & ProfileOptions;
108
+ export type IFrameOptions = {
109
+ /** The ID of the starter pack to use */
110
+ starterPackId?: string;
111
+ /** The preset to use */
112
+ preset?: string;
113
+ };
114
+ export type Chain = {
115
+ rpcUrl: string;
116
+ };
117
+ export type ProviderOptions = {
118
+ defaultChainId: ChainId;
119
+ chains: Chain[];
120
+ };
121
+ export type KeychainOptions = IFrameOptions & {
122
+ policies?: SessionPolicies;
123
+ /** The URL of keychain */
124
+ url?: string;
125
+ /** The origin of keychain */
126
+ origin?: string;
127
+ /** Propagate transaction errors back to caller instead of showing modal */
128
+ propagateSessionErrors?: boolean;
129
+ };
130
+ export type ProfileOptions = IFrameOptions & {
131
+ /** The URL of profile. Mainly for internal development purpose */
132
+ profileUrl?: string;
133
+ /** The project name of Slot instance. */
134
+ slot?: string;
135
+ /** The namespace to use to fetch trophies data from indexer. Will be mandatory once profile page is in production */
136
+ namespace?: string;
137
+ /** The tokens to be listed on Inventory modal */
138
+ tokens?: Tokens;
139
+ /** The policies to use for the profile */
140
+ policies?: SessionPolicies;
141
+ };
142
+ export type ProfileContextTypeVariant = "inventory" | "trophies" | "achievements" | "activity";
143
+ export type Tokens = {
144
+ erc20?: string[];
145
+ };
146
+ export {};
@@ -0,0 +1,15 @@
1
+ import { Call } from 'starknet';
2
+ import { default as wasm } from '@cartridge/account-wasm/controller';
3
+ import { Policies, SessionPolicies } from '@cartridge/presets';
4
+ import { ChainId } from '@starknet-io/types-js';
5
+ import { ParsedSessionPolicies } from './policies';
6
+ export declare function normalizeCalls(calls: Call | Call[]): {
7
+ entrypoint: string;
8
+ contractAddress: string;
9
+ calldata: import('starknet').HexCalldata;
10
+ }[];
11
+ export declare function toSessionPolicies(policies: Policies): SessionPolicies;
12
+ export declare function toWasmPolicies(policies: ParsedSessionPolicies): wasm.Policy[];
13
+ export declare function toArray<T>(val: T | T[]): T[];
14
+ export declare function humanizeString(str: string): string;
15
+ export declare function parseChainId(url: URL): Promise<ChainId>;
@@ -0,0 +1,14 @@
1
+ import { WalletAdapter, ExternalWallet, ExternalWalletResponse, ExternalWalletType, ExternalPlatform } from '../types';
2
+ import { TypedData } from '@starknet-io/types-js';
3
+ export declare class ArgentWallet implements WalletAdapter {
4
+ readonly type: ExternalWalletType;
5
+ readonly platform: ExternalPlatform;
6
+ private wallet;
7
+ private account;
8
+ isAvailable(): boolean;
9
+ getInfo(): ExternalWallet;
10
+ connect(): Promise<ExternalWalletResponse<any>>;
11
+ signTypedData(data: TypedData): Promise<ExternalWalletResponse<any>>;
12
+ switchChain(_chainId: string): Promise<boolean>;
13
+ getBalance(_tokenAddress?: string): Promise<ExternalWalletResponse<any>>;
14
+ }
@@ -0,0 +1,29 @@
1
+ import { ExternalWalletType, ExternalWallet, ExternalWalletResponse } from './types';
2
+ export declare class WalletBridge {
3
+ private readonly walletAdapters;
4
+ private readonly connectedWallets;
5
+ constructor();
6
+ getIFrameMethods(): {
7
+ externalDetectWallets: (_origin: string) => () => Promise<ExternalWallet[]>;
8
+ externalConnectWallet: (_origin: string) => (type: ExternalWalletType) => Promise<ExternalWalletResponse<unknown>>;
9
+ externalSignMessage: (_origin: string) => (type: ExternalWalletType, message: string) => Promise<ExternalWalletResponse<unknown>>;
10
+ externalSignTypedData: (_origin: string) => (type: ExternalWalletType, data: any) => Promise<ExternalWalletResponse<unknown>>;
11
+ externalGetBalance: (_origin: string) => (type: ExternalWalletType, tokenAddress?: string) => Promise<ExternalWalletResponse<unknown>>;
12
+ };
13
+ detectWallets(): Promise<ExternalWallet[]>;
14
+ private getWalletAdapter;
15
+ private handleError;
16
+ connectWallet(type: ExternalWalletType): Promise<ExternalWalletResponse>;
17
+ signMessage(type: ExternalWalletType, message: string): Promise<ExternalWalletResponse>;
18
+ signTypedData(type: ExternalWalletType, data: any): Promise<ExternalWalletResponse>;
19
+ getBalance(type: ExternalWalletType, tokenAddress?: string): Promise<ExternalWalletResponse>;
20
+ }
21
+ declare global {
22
+ interface Window {
23
+ ethereum?: any;
24
+ solana?: any;
25
+ starknet_argentX?: any;
26
+ wallet_bridge?: WalletBridge;
27
+ }
28
+ }
29
+ export type { ExternalWalletType, ExternalWallet, ExternalWalletResponse, WalletAdapter, } from './types';
@@ -0,0 +1,5 @@
1
+ export * from './types';
2
+ export * from './bridge';
3
+ export * from './metamask';
4
+ export * from './phantom';
5
+ export * from './argent';
@@ -0,0 +1,16 @@
1
+ import { WalletAdapter, ExternalWallet, ExternalWalletResponse, ExternalWalletType, ExternalPlatform } from '../types';
2
+ export declare class MetaMaskWallet implements WalletAdapter {
3
+ readonly type: ExternalWalletType;
4
+ readonly platform: ExternalPlatform;
5
+ private MMSDK;
6
+ private account;
7
+ constructor();
8
+ isAvailable(): boolean;
9
+ getInfo(): ExternalWallet;
10
+ connect(): Promise<ExternalWalletResponse<any>>;
11
+ signTransaction(transaction: any): Promise<ExternalWalletResponse<any>>;
12
+ signMessage(message: string): Promise<ExternalWalletResponse<any>>;
13
+ signTypedData(data: any): Promise<ExternalWalletResponse<any>>;
14
+ switchChain(chainId: string): Promise<boolean>;
15
+ getBalance(tokenAddress?: string): Promise<ExternalWalletResponse<any>>;
16
+ }
@@ -0,0 +1,13 @@
1
+ import { WalletAdapter, ExternalWallet, ExternalWalletResponse, ExternalWalletType, ExternalPlatform } from '../types';
2
+ export declare class PhantomWallet implements WalletAdapter {
3
+ readonly type: ExternalWalletType;
4
+ readonly platform: ExternalPlatform;
5
+ private account;
6
+ isAvailable(): boolean;
7
+ getInfo(): ExternalWallet;
8
+ connect(): Promise<ExternalWalletResponse<any>>;
9
+ signTransaction(transaction: any): Promise<ExternalWalletResponse<any>>;
10
+ signMessage(message: string): Promise<ExternalWalletResponse<any>>;
11
+ switchChain(_chainId: string): Promise<boolean>;
12
+ getBalance(_tokenAddress?: string): Promise<ExternalWalletResponse<any>>;
13
+ }
@@ -0,0 +1,27 @@
1
+ export type ExternalWalletType = "argent" | "metamask" | "phantom";
2
+ export type ExternalPlatform = "starknet" | "ethereum" | "solana";
3
+ export interface ExternalWallet {
4
+ type: ExternalWalletType;
5
+ available: boolean;
6
+ version?: string;
7
+ chainId?: string;
8
+ name?: string;
9
+ platform?: ExternalPlatform;
10
+ }
11
+ export interface ExternalWalletResponse<T = unknown> {
12
+ success: boolean;
13
+ wallet: ExternalWalletType;
14
+ result?: T;
15
+ error?: string;
16
+ account?: string;
17
+ }
18
+ export interface WalletAdapter {
19
+ type: ExternalWalletType;
20
+ platform: ExternalPlatform;
21
+ isAvailable(): boolean;
22
+ getInfo(): ExternalWallet;
23
+ connect(): Promise<ExternalWalletResponse<any>>;
24
+ signMessage?(message: string): Promise<ExternalWalletResponse<any>>;
25
+ signTypedData?(data: any): Promise<ExternalWalletResponse<any>>;
26
+ getBalance(tokenAddress?: string): Promise<ExternalWalletResponse<any>>;
27
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cartridge/controller",
3
- "version": "0.7.7",
3
+ "version": "0.7.9-alpha.1",
4
4
  "description": "Cartridge Controller",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,75 +8,55 @@
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js",
12
- "require": "./dist/index.cjs"
11
+ "import": "./dist/index.js"
13
12
  },
14
13
  "./session": {
15
- "types": "./dist/session/index.d.ts",
16
- "import": "./dist/session/index.js",
17
- "require": "./dist/session/index.cjs"
14
+ "types": "./dist/session.d.ts",
15
+ "import": "./dist/session.js"
18
16
  },
19
17
  "./session/node": {
20
18
  "types": "./dist/node/index.d.ts",
21
19
  "import": "./dist/node/index.js",
22
20
  "require": "./dist/node/index.cjs"
23
- },
24
- "./provider": {
25
- "types": "./dist/provider/index.d.ts",
26
- "import": "./dist/provider/index.js"
27
- },
28
- "./types": {
29
- "types": "./dist/types/index.d.ts",
30
- "import": "./dist/types/index.js"
31
21
  }
32
22
  },
33
- "tsup": {
34
- "entry": [
35
- "src/index.ts",
36
- "src/controller.ts",
37
- "src/lookup.ts",
38
- "src/session/index.ts",
39
- "src/node/index.ts"
40
- ],
41
- "format": [
42
- "esm",
43
- "cjs"
44
- ],
45
- "splitting": false,
46
- "sourcemap": true,
47
- "clean": true,
48
- "dts": true,
49
- "treeshake": {
50
- "preset": "recommended"
51
- },
52
- "exports": "named"
53
- },
54
23
  "peerDependencies": {
24
+ "@metamask/sdk": "^0.32.1",
25
+ "@phantom/wallet-sdk": "^0.0.23",
26
+ "open": "^10.1.0",
55
27
  "starknet": "^6.21.0",
56
- "open": "^10.1.0"
28
+ "starknetkit": "^2.6.1"
57
29
  },
58
30
  "dependencies": {
59
31
  "@cartridge/penpal": "^6.2.4",
32
+ "@metamask/sdk": "^0.32.1",
60
33
  "@starknet-io/types-js": "^0.7.7",
61
34
  "@telegram-apps/sdk": "^2.4.0",
62
- "base64url": "^3.0.1",
63
35
  "cbor-x": "^1.5.0",
64
36
  "fast-deep-equal": "^3.1.3",
65
- "@cartridge/account-wasm": "0.7.7"
37
+ "@cartridge/account-wasm": "0.7.9-alpha.1"
66
38
  },
67
39
  "devDependencies": {
68
40
  "@types/jest": "^29.5.14",
69
41
  "@types/node": "^18.0.6",
70
42
  "jest": "^29.7.0",
71
43
  "prettier": "^3.4.2",
44
+ "rollup-plugin-visualizer": "^5.12.0",
72
45
  "ts-jest": "^29.2.5",
73
46
  "tsup": "^8.0.1",
74
47
  "typescript": "^5.7.3",
75
- "@cartridge/tsconfig": "0.7.7"
48
+ "vite": "^6.0.0",
49
+ "vite-plugin-dts": "^4.5.3",
50
+ "vite-plugin-node-polyfills": "^0.22.0",
51
+ "vite-plugin-top-level-await": "^1.4.4",
52
+ "vite-plugin-wasm": "^3.4.1",
53
+ "@cartridge/tsconfig": "0.7.9-alpha.1"
76
54
  },
77
55
  "scripts": {
78
- "build:deps": "tsup",
79
- "build": "pnpm build:deps",
56
+ "build:deps": "pnpm build",
57
+ "build:browser": "vite build",
58
+ "build:node": "tsup --config tsup.node.config.ts",
59
+ "build": "pnpm build:browser && pnpm build:node",
80
60
  "format": "prettier --write \"src/**/*.ts\"",
81
61
  "format:check": "prettier --check \"src/**/*.ts\"",
82
62
  "test": "jest",
@@ -75,7 +75,7 @@ export class IFrame<CallSender extends {}> implements Modal {
75
75
 
76
76
  connectToChild<CallSender>({
77
77
  iframe: this.iframe,
78
- methods: { close: () => this.close(), ...methods },
78
+ methods: { close: (_origin: string) => () => this.close(), ...methods },
79
79
  }).promise.then(onConnect);
80
80
 
81
81
  this.resize();
@@ -1,12 +1,16 @@
1
1
  import { KEYCHAIN_URL } from "../constants";
2
2
  import { Keychain, KeychainOptions } from "../types";
3
+ import { WalletBridge } from "../wallets/bridge";
3
4
  import { IFrame, IFrameOptions } from "./base";
4
5
 
5
6
  type KeychainIframeOptions = IFrameOptions<Keychain> & KeychainOptions;
6
7
 
7
8
  export class KeychainIFrame extends IFrame<Keychain> {
9
+ private walletBridge: WalletBridge;
10
+
8
11
  constructor({ url, policies, ...iframeOptions }: KeychainIframeOptions) {
9
12
  const _url = new URL(url ?? KEYCHAIN_URL);
13
+ const walletBridge = new WalletBridge();
10
14
 
11
15
  if (policies) {
12
16
  _url.searchParams.set(
@@ -19,6 +23,13 @@ export class KeychainIFrame extends IFrame<Keychain> {
19
23
  ...iframeOptions,
20
24
  id: "controller-keychain",
21
25
  url: _url,
26
+ methods: walletBridge.getIFrameMethods(),
22
27
  });
28
+
29
+ this.walletBridge = walletBridge;
30
+ }
31
+
32
+ getWalletBridge(): WalletBridge {
33
+ return this.walletBridge;
23
34
  }
24
35
  }
@@ -26,16 +26,18 @@ export class ProfileIFrame extends IFrame<Profile> {
26
26
  const _profileUrl = (profileUrl || PROFILE_URL).replace(/\/$/, "");
27
27
  let _url = new URL(
28
28
  slot
29
- ? namespace
30
- ? `${_profileUrl}/account/${username}/slot/${slot}?ps=${encodeURIComponent(
31
- slot,
32
- )}&ns=${encodeURIComponent(namespace)}`
33
- : `${_profileUrl}/account/${username}/slot/${slot}?ps=${encodeURIComponent(
34
- slot,
35
- )}`
29
+ ? `${_profileUrl}/account/${username}/slot/${slot}`
36
30
  : `${_profileUrl}/account/${username}`,
37
31
  );
38
32
 
33
+ if (slot) {
34
+ _url.searchParams.set("ps", encodeURIComponent(slot));
35
+ }
36
+
37
+ if (namespace) {
38
+ _url.searchParams.set("ns", encodeURIComponent(namespace));
39
+ }
40
+
39
41
  if (version) {
40
42
  _url.searchParams.set("v", encodeURIComponent(version));
41
43
  }
package/src/index.ts CHANGED
@@ -3,4 +3,5 @@ export * from "./errors";
3
3
  export * from "./types";
4
4
  export * from "./lookup";
5
5
  export * from "./utils";
6
+ export * from "./wallets";
6
7
  export * from "@cartridge/presets";
package/src/node/index.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { default } from "./provider";
2
2
  export * from "./provider";
3
3
  export * from "../errors";
4
- export * from "../types";
4
+ export type { ControllerError } from "../types";
package/src/types.ts CHANGED
@@ -13,6 +13,11 @@ import {
13
13
  } from "@starknet-io/types-js";
14
14
  import { KeychainIFrame, ProfileIFrame } from "./iframe";
15
15
  import { Policy, SessionPolicies } from "@cartridge/presets";
16
+ import {
17
+ ExternalWallet,
18
+ ExternalWalletResponse,
19
+ ExternalWalletType,
20
+ } from "./wallets/types";
16
21
 
17
22
  export type Session = {
18
23
  chainId: constants.StarknetChainId;
@@ -129,6 +134,25 @@ export interface Keychain {
129
134
  openPurchaseCredits(): void;
130
135
  openExecute(calls: Call[]): Promise<void>;
131
136
  switchChain(rpcUrl: string): Promise<void>;
137
+
138
+ // External wallet methods
139
+ externalDetectWallets(): Promise<ExternalWallet[]>;
140
+ externalConnectWallet(
141
+ type: ExternalWalletType,
142
+ ): Promise<ExternalWalletResponse>;
143
+ externalSignMessage(
144
+ type: ExternalWalletType,
145
+ message: string,
146
+ ): Promise<ExternalWalletResponse>;
147
+ externalSignTypedData(
148
+ type: ExternalWalletType,
149
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
150
+ data: any,
151
+ ): Promise<ExternalWalletResponse>;
152
+ externalGetBalance(
153
+ type: ExternalWalletType,
154
+ tokenAddress?: string,
155
+ ): Promise<ExternalWalletResponse>;
132
156
  }
133
157
 
134
158
  export interface Profile {
@@ -0,0 +1,122 @@
1
+ import {
2
+ WalletAdapter,
3
+ ExternalWallet,
4
+ ExternalWalletResponse,
5
+ ExternalWalletType,
6
+ ExternalPlatform,
7
+ } from "../types";
8
+ import { connect, StarknetWindowObject } from "starknetkit";
9
+ import { InjectedConnector } from "starknetkit/injected";
10
+ import { TypedData } from "@starknet-io/types-js";
11
+
12
+ export class ArgentWallet implements WalletAdapter {
13
+ readonly type: ExternalWalletType = "argent";
14
+ readonly platform: ExternalPlatform = "starknet";
15
+ private wallet: StarknetWindowObject | undefined = undefined;
16
+ private account: string | undefined = undefined;
17
+
18
+ isAvailable(): boolean {
19
+ return typeof window !== "undefined" && !!window.starknet_argentX;
20
+ }
21
+
22
+ getInfo(): ExternalWallet {
23
+ const available = this.isAvailable();
24
+
25
+ return {
26
+ type: this.type,
27
+ available,
28
+ version: available
29
+ ? window.starknet_argentX?.version || "Unknown"
30
+ : undefined,
31
+ chainId: available ? window.starknet_argentX?.chainId : undefined,
32
+ name: "Argent",
33
+ platform: this.platform,
34
+ };
35
+ }
36
+
37
+ async connect(): Promise<ExternalWalletResponse<any>> {
38
+ if (this.account) {
39
+ return { success: true, wallet: this.type, account: this.account };
40
+ }
41
+
42
+ try {
43
+ if (!this.isAvailable()) {
44
+ throw new Error("Argent is not available");
45
+ }
46
+
47
+ const { wallet, connectorData } = await connect({
48
+ connectors: [new InjectedConnector({ options: { id: "argentX" } })],
49
+ });
50
+
51
+ if (!wallet) {
52
+ throw new Error("No wallet found");
53
+ }
54
+
55
+ this.wallet = wallet;
56
+ this.account = connectorData?.account;
57
+ return { success: true, wallet: this.type, account: this.account };
58
+ } catch (error) {
59
+ console.error(`Error connecting to Argent:`, error);
60
+ return {
61
+ success: false,
62
+ wallet: this.type,
63
+ error: (error as Error).message || "Unknown error",
64
+ };
65
+ }
66
+ }
67
+
68
+ async signTypedData(data: TypedData): Promise<ExternalWalletResponse<any>> {
69
+ try {
70
+ if (!this.isAvailable() || !this.wallet) {
71
+ throw new Error("Argent is not connected");
72
+ }
73
+
74
+ console.log("signTypedData", data);
75
+
76
+ const sig = await this.wallet.request({
77
+ type: "wallet_signTypedData",
78
+ params: data,
79
+ });
80
+
81
+ return { success: true, wallet: this.type, result: sig };
82
+ } catch (error) {
83
+ console.error(`Error signing typed data with Argent:`, error);
84
+ return {
85
+ success: false,
86
+ wallet: this.type,
87
+ error: (error as Error).message || "Unknown error",
88
+ };
89
+ }
90
+ }
91
+
92
+ async switchChain(_chainId: string): Promise<boolean> {
93
+ console.warn(
94
+ "Chain switching for Argent may require custom implementation",
95
+ );
96
+ return false;
97
+ }
98
+
99
+ async getBalance(
100
+ _tokenAddress?: string,
101
+ ): Promise<ExternalWalletResponse<any>> {
102
+ try {
103
+ if (!this.isAvailable() || !this.wallet) {
104
+ throw new Error("Argent is not connected");
105
+ }
106
+
107
+ // TODO: Implement balance fetching based on Argent's API
108
+ return {
109
+ success: true,
110
+ wallet: this.type,
111
+ result: "Implement based on Argent API",
112
+ };
113
+ } catch (error) {
114
+ console.error(`Error getting balance from Argent:`, error);
115
+ return {
116
+ success: false,
117
+ wallet: this.type,
118
+ error: (error as Error).message || "Unknown error",
119
+ };
120
+ }
121
+ }
122
+ }