@cartridge/connector 0.13.4 → 0.13.6
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/.turbo/turbo-build$colon$deps.log +11 -11
- package/dist/controller.d.ts +7 -6
- package/dist/controller.js +14 -10
- package/dist/controller.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +19 -11
- package/dist/index.js.map +1 -1
- package/dist/session.js +5 -1
- package/dist/session.js.map +1 -1
- package/package.json +7 -4
- package/src/__tests__/controller.test.ts +90 -0
- package/src/controller.ts +30 -17
- package/src/session.ts +6 -1
- package/vitest.config.ts +9 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @cartridge/connector@0.13.
|
|
2
|
+
> @cartridge/connector@0.13.6 build:deps /home/runner/work/controller/controller/packages/connector
|
|
3
3
|
> tsup --dts-resolve
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/controller.ts, src/index.ts, src/session.ts
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
[34mCLI[39m Target: esnext
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
|
-
[32mESM[39m [1mdist/
|
|
13
|
-
[32mESM[39m [1mdist/
|
|
14
|
-
[32mESM[39m [1mdist/
|
|
15
|
-
[32mESM[39m [1mdist/
|
|
16
|
-
[32mESM[39m [1mdist/
|
|
17
|
-
[32mESM[39m [1mdist/
|
|
18
|
-
[32mESM[39m ⚡️ Build success in
|
|
12
|
+
[32mESM[39m [1mdist/index.js [22m[32m2.83 KB[39m
|
|
13
|
+
[32mESM[39m [1mdist/session.js [22m[32m916.00 B[39m
|
|
14
|
+
[32mESM[39m [1mdist/controller.js [22m[32m1.98 KB[39m
|
|
15
|
+
[32mESM[39m [1mdist/index.js.map [22m[32m5.84 KB[39m
|
|
16
|
+
[32mESM[39m [1mdist/session.js.map [22m[32m1.73 KB[39m
|
|
17
|
+
[32mESM[39m [1mdist/controller.js.map [22m[32m4.15 KB[39m
|
|
18
|
+
[32mESM[39m ⚡️ Build success in 44ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
22
|
-
[32mDTS[39m [1mdist/controller.d.ts [22m[
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 6912ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m290.00 B[39m
|
|
22
|
+
[32mDTS[39m [1mdist/controller.d.ts [22m[32m947.00 B[39m
|
|
23
23
|
[32mDTS[39m [1mdist/session.d.ts [22m[32m476.00 B[39m
|
package/dist/controller.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import ControllerProvider, { ControllerOptions,
|
|
1
|
+
import * as _starknet_io_get_starknet_wallet_standard_features from '@starknet-io/get-starknet-wallet-standard/features';
|
|
2
|
+
import ControllerProvider, { ControllerOptions, ConnectOptions } from '@cartridge/controller';
|
|
3
3
|
import { InjectedConnector, Connector } from '@starknet-react/core';
|
|
4
|
-
import { WalletWithStarknetFeatures } from '@starknet-io/get-starknet-wallet-standard/features';
|
|
5
4
|
|
|
6
5
|
declare class ControllerConnector extends InjectedConnector {
|
|
7
6
|
controller: ControllerProvider;
|
|
@@ -12,10 +11,12 @@ declare class ControllerConnector extends InjectedConnector {
|
|
|
12
11
|
delegateAccount(): Promise<string | null>;
|
|
13
12
|
connect(args?: {
|
|
14
13
|
chainIdHint?: bigint;
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
} & ConnectOptions): Promise<{
|
|
15
|
+
account: string;
|
|
16
|
+
chainId?: bigint;
|
|
17
|
+
}>;
|
|
17
18
|
static fromConnectors(connectors: Connector[]): ControllerConnector;
|
|
18
|
-
asWalletStandard(): WalletWithStarknetFeatures;
|
|
19
|
+
asWalletStandard(): _starknet_io_get_starknet_wallet_standard_features.WalletWithStarknetFeatures;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export { ControllerConnector as default };
|
package/dist/controller.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// src/controller.ts
|
|
2
2
|
import ControllerProvider from "@cartridge/controller";
|
|
3
3
|
import { InjectedConnector } from "@starknet-react/core";
|
|
4
|
-
import { StarknetInjectedWallet } from "@starknet-io/get-starknet-wallet-standard";
|
|
5
4
|
var ControllerConnector = class extends InjectedConnector {
|
|
6
5
|
controller;
|
|
7
6
|
constructor(options = {}) {
|
|
@@ -18,7 +17,11 @@ var ControllerConnector = class extends InjectedConnector {
|
|
|
18
17
|
this.controller = controller;
|
|
19
18
|
}
|
|
20
19
|
async disconnect() {
|
|
21
|
-
this.controller.disconnect();
|
|
20
|
+
await this.controller.disconnect();
|
|
21
|
+
try {
|
|
22
|
+
await super.disconnect();
|
|
23
|
+
} catch {
|
|
24
|
+
}
|
|
22
25
|
}
|
|
23
26
|
username() {
|
|
24
27
|
return this.controller.username();
|
|
@@ -30,11 +33,17 @@ var ControllerConnector = class extends InjectedConnector {
|
|
|
30
33
|
return await this.controller.delegateAccount();
|
|
31
34
|
}
|
|
32
35
|
async connect(args) {
|
|
33
|
-
const
|
|
36
|
+
const { chainIdHint, ...connectOptions } = args ?? {};
|
|
37
|
+
const controllerArgs = args && Object.keys(connectOptions).length > 0 ? connectOptions : void 0;
|
|
38
|
+
const account = await this.controller.connect(controllerArgs);
|
|
34
39
|
if (!account) {
|
|
35
40
|
throw new Error("Failed to connect controller");
|
|
36
41
|
}
|
|
37
|
-
|
|
42
|
+
if (typeof window !== "undefined") {
|
|
43
|
+
window.starknet_controller = this.controller;
|
|
44
|
+
}
|
|
45
|
+
const data = await super.connect({ chainIdHint });
|
|
46
|
+
return { ...data, account: account.address };
|
|
38
47
|
}
|
|
39
48
|
static fromConnectors(connectors) {
|
|
40
49
|
const connector = connectors.find((c) => c.id === "controller");
|
|
@@ -44,12 +53,7 @@ var ControllerConnector = class extends InjectedConnector {
|
|
|
44
53
|
return connector;
|
|
45
54
|
}
|
|
46
55
|
asWalletStandard() {
|
|
47
|
-
|
|
48
|
-
console.warn(
|
|
49
|
-
`Casting Controller to WalletWithStarknetFeatures is an experimental feature and may contain bugs. Please report any issues at https://github.com/cartridge-gg/controller/issues`
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
return new StarknetInjectedWallet(this.controller);
|
|
56
|
+
return this.controller.asWalletStandard();
|
|
53
57
|
}
|
|
54
58
|
};
|
|
55
59
|
export {
|
package/dist/controller.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/controller.ts"],"sourcesContent":["import ControllerProvider, {\n
|
|
1
|
+
{"version":3,"sources":["../src/controller.ts"],"sourcesContent":["import ControllerProvider, {\n ConnectOptions,\n ControllerOptions,\n} from \"@cartridge/controller\";\nimport { Connector, InjectedConnector } from \"@starknet-react/core\";\n\nexport default class ControllerConnector extends InjectedConnector {\n public controller: ControllerProvider;\n\n constructor(options: ControllerOptions = {}) {\n let controller: ControllerProvider;\n\n if (typeof window !== \"undefined\" && (window as any).starknet_controller) {\n console.warn(\n \"ControllerConnector was instantiated multiple times. \" +\n \"Reusing existing controller to prevent errors. \" +\n \"To fix, create the connector at the module level instead of inside a React component.\",\n );\n controller = (window as any).starknet_controller;\n } else {\n controller = new ControllerProvider(options);\n }\n\n super({ options: { id: controller.id, name: controller.name } });\n this.controller = controller;\n }\n\n async disconnect() {\n await this.controller.disconnect();\n try {\n await super.disconnect();\n } catch {\n // Best-effort: starknet-react may call disconnect even when the injected wallet isn't present.\n }\n }\n\n username() {\n return this.controller.username();\n }\n\n isReady(): boolean {\n return this.controller.isReady();\n }\n\n async delegateAccount() {\n return await this.controller.delegateAccount();\n }\n\n async connect(args?: { chainIdHint?: bigint } & ConnectOptions) {\n const { chainIdHint, ...connectOptions } = args ?? {};\n const controllerArgs =\n args && Object.keys(connectOptions).length > 0\n ? (connectOptions as ConnectOptions)\n : undefined;\n\n const account = await this.controller.connect(controllerArgs);\n if (!account) {\n throw new Error(\"Failed to connect controller\");\n }\n\n // Ensure the injected wallet instance used by starknet-react (window.starknet_controller)\n // always points at the same ControllerProvider instance this connector wraps.\n if (typeof window !== \"undefined\") {\n (window as any).starknet_controller = this.controller;\n }\n\n const data = await super.connect({ chainIdHint });\n\n // `@starknet-react/core` updates its state from the `account` returned here.\n // Use the authoritative address from `controller.connect()` to avoid edge cases\n // where the injected wallet request returns an empty/undefined account.\n return { ...data, account: account.address };\n }\n\n static fromConnectors(connectors: Connector[]): ControllerConnector {\n const connector = connectors.find((c) => c.id === \"controller\");\n if (!connector) {\n throw new Error(\"Controller connector not found\");\n }\n return connector as ControllerConnector;\n }\n\n asWalletStandard() {\n return this.controller.asWalletStandard();\n }\n}\n"],"mappings":";AAAA,OAAO,wBAGA;AACP,SAAoB,yBAAyB;AAE7C,IAAqB,sBAArB,cAAiD,kBAAkB;AAAA,EAC1D;AAAA,EAEP,YAAY,UAA6B,CAAC,GAAG;AAC3C,QAAI;AAEJ,QAAI,OAAO,WAAW,eAAgB,OAAe,qBAAqB;AACxE,cAAQ;AAAA,QACN;AAAA,MAGF;AACA,mBAAc,OAAe;AAAA,IAC/B,OAAO;AACL,mBAAa,IAAI,mBAAmB,OAAO;AAAA,IAC7C;AAEA,UAAM,EAAE,SAAS,EAAE,IAAI,WAAW,IAAI,MAAM,WAAW,KAAK,EAAE,CAAC;AAC/D,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAM,aAAa;AACjB,UAAM,KAAK,WAAW,WAAW;AACjC,QAAI;AACF,YAAM,MAAM,WAAW;AAAA,IACzB,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,WAAW;AACT,WAAO,KAAK,WAAW,SAAS;AAAA,EAClC;AAAA,EAEA,UAAmB;AACjB,WAAO,KAAK,WAAW,QAAQ;AAAA,EACjC;AAAA,EAEA,MAAM,kBAAkB;AACtB,WAAO,MAAM,KAAK,WAAW,gBAAgB;AAAA,EAC/C;AAAA,EAEA,MAAM,QAAQ,MAAkD;AAC9D,UAAM,EAAE,aAAa,GAAG,eAAe,IAAI,QAAQ,CAAC;AACpD,UAAM,iBACJ,QAAQ,OAAO,KAAK,cAAc,EAAE,SAAS,IACxC,iBACD;AAEN,UAAM,UAAU,MAAM,KAAK,WAAW,QAAQ,cAAc;AAC5D,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAIA,QAAI,OAAO,WAAW,aAAa;AACjC,MAAC,OAAe,sBAAsB,KAAK;AAAA,IAC7C;AAEA,UAAM,OAAO,MAAM,MAAM,QAAQ,EAAE,YAAY,CAAC;AAKhD,WAAO,EAAE,GAAG,MAAM,SAAS,QAAQ,QAAQ;AAAA,EAC7C;AAAA,EAEA,OAAO,eAAe,YAA8C;AAClE,UAAM,YAAY,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY;AAC9D,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,mBAAmB;AACjB,WAAO,KAAK,WAAW,iBAAiB;AAAA,EAC1C;AACF;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { default as ControllerConnector } from './controller.js';
|
|
2
2
|
export { default as SessionConnector } from './session.js';
|
|
3
|
-
import '
|
|
3
|
+
import '@starknet-io/get-starknet-wallet-standard/features';
|
|
4
4
|
import '@cartridge/controller';
|
|
5
5
|
import '@starknet-react/core';
|
|
6
|
-
import '@starknet-io/get-starknet-wallet-standard/features';
|
|
7
6
|
import '@cartridge/controller/session';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// src/controller.ts
|
|
2
2
|
import ControllerProvider from "@cartridge/controller";
|
|
3
3
|
import { InjectedConnector } from "@starknet-react/core";
|
|
4
|
-
import { StarknetInjectedWallet } from "@starknet-io/get-starknet-wallet-standard";
|
|
5
4
|
var ControllerConnector = class extends InjectedConnector {
|
|
6
5
|
controller;
|
|
7
6
|
constructor(options = {}) {
|
|
@@ -18,7 +17,11 @@ var ControllerConnector = class extends InjectedConnector {
|
|
|
18
17
|
this.controller = controller;
|
|
19
18
|
}
|
|
20
19
|
async disconnect() {
|
|
21
|
-
this.controller.disconnect();
|
|
20
|
+
await this.controller.disconnect();
|
|
21
|
+
try {
|
|
22
|
+
await super.disconnect();
|
|
23
|
+
} catch {
|
|
24
|
+
}
|
|
22
25
|
}
|
|
23
26
|
username() {
|
|
24
27
|
return this.controller.username();
|
|
@@ -30,11 +33,17 @@ var ControllerConnector = class extends InjectedConnector {
|
|
|
30
33
|
return await this.controller.delegateAccount();
|
|
31
34
|
}
|
|
32
35
|
async connect(args) {
|
|
33
|
-
const
|
|
36
|
+
const { chainIdHint, ...connectOptions } = args ?? {};
|
|
37
|
+
const controllerArgs = args && Object.keys(connectOptions).length > 0 ? connectOptions : void 0;
|
|
38
|
+
const account = await this.controller.connect(controllerArgs);
|
|
34
39
|
if (!account) {
|
|
35
40
|
throw new Error("Failed to connect controller");
|
|
36
41
|
}
|
|
37
|
-
|
|
42
|
+
if (typeof window !== "undefined") {
|
|
43
|
+
window.starknet_controller = this.controller;
|
|
44
|
+
}
|
|
45
|
+
const data = await super.connect({ chainIdHint });
|
|
46
|
+
return { ...data, account: account.address };
|
|
38
47
|
}
|
|
39
48
|
static fromConnectors(connectors) {
|
|
40
49
|
const connector = connectors.find((c) => c.id === "controller");
|
|
@@ -44,12 +53,7 @@ var ControllerConnector = class extends InjectedConnector {
|
|
|
44
53
|
return connector;
|
|
45
54
|
}
|
|
46
55
|
asWalletStandard() {
|
|
47
|
-
|
|
48
|
-
console.warn(
|
|
49
|
-
`Casting Controller to WalletWithStarknetFeatures is an experimental feature and may contain bugs. Please report any issues at https://github.com/cartridge-gg/controller/issues`
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
return new StarknetInjectedWallet(this.controller);
|
|
56
|
+
return this.controller.asWalletStandard();
|
|
53
57
|
}
|
|
54
58
|
};
|
|
55
59
|
|
|
@@ -69,7 +73,11 @@ var SessionConnector = class extends InjectedConnector2 {
|
|
|
69
73
|
this.controller = controller;
|
|
70
74
|
}
|
|
71
75
|
async disconnect() {
|
|
72
|
-
this.controller.disconnect();
|
|
76
|
+
await this.controller.disconnect();
|
|
77
|
+
try {
|
|
78
|
+
await super.disconnect();
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
73
81
|
}
|
|
74
82
|
static fromConnectors(connectors) {
|
|
75
83
|
const connector = connectors.find((c) => c.id === "controller_session");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/controller.ts","../src/session.ts"],"sourcesContent":["import ControllerProvider, {\n
|
|
1
|
+
{"version":3,"sources":["../src/controller.ts","../src/session.ts"],"sourcesContent":["import ControllerProvider, {\n ConnectOptions,\n ControllerOptions,\n} from \"@cartridge/controller\";\nimport { Connector, InjectedConnector } from \"@starknet-react/core\";\n\nexport default class ControllerConnector extends InjectedConnector {\n public controller: ControllerProvider;\n\n constructor(options: ControllerOptions = {}) {\n let controller: ControllerProvider;\n\n if (typeof window !== \"undefined\" && (window as any).starknet_controller) {\n console.warn(\n \"ControllerConnector was instantiated multiple times. \" +\n \"Reusing existing controller to prevent errors. \" +\n \"To fix, create the connector at the module level instead of inside a React component.\",\n );\n controller = (window as any).starknet_controller;\n } else {\n controller = new ControllerProvider(options);\n }\n\n super({ options: { id: controller.id, name: controller.name } });\n this.controller = controller;\n }\n\n async disconnect() {\n await this.controller.disconnect();\n try {\n await super.disconnect();\n } catch {\n // Best-effort: starknet-react may call disconnect even when the injected wallet isn't present.\n }\n }\n\n username() {\n return this.controller.username();\n }\n\n isReady(): boolean {\n return this.controller.isReady();\n }\n\n async delegateAccount() {\n return await this.controller.delegateAccount();\n }\n\n async connect(args?: { chainIdHint?: bigint } & ConnectOptions) {\n const { chainIdHint, ...connectOptions } = args ?? {};\n const controllerArgs =\n args && Object.keys(connectOptions).length > 0\n ? (connectOptions as ConnectOptions)\n : undefined;\n\n const account = await this.controller.connect(controllerArgs);\n if (!account) {\n throw new Error(\"Failed to connect controller\");\n }\n\n // Ensure the injected wallet instance used by starknet-react (window.starknet_controller)\n // always points at the same ControllerProvider instance this connector wraps.\n if (typeof window !== \"undefined\") {\n (window as any).starknet_controller = this.controller;\n }\n\n const data = await super.connect({ chainIdHint });\n\n // `@starknet-react/core` updates its state from the `account` returned here.\n // Use the authoritative address from `controller.connect()` to avoid edge cases\n // where the injected wallet request returns an empty/undefined account.\n return { ...data, account: account.address };\n }\n\n static fromConnectors(connectors: Connector[]): ControllerConnector {\n const connector = connectors.find((c) => c.id === \"controller\");\n if (!connector) {\n throw new Error(\"Controller connector not found\");\n }\n return connector as ControllerConnector;\n }\n\n asWalletStandard() {\n return this.controller.asWalletStandard();\n }\n}\n","import SessionProvider, { SessionOptions } from \"@cartridge/controller/session\";\nimport { Connector, InjectedConnector } from \"@starknet-react/core\";\n\nexport default class SessionConnector extends InjectedConnector {\n public controller: SessionProvider;\n\n constructor(options: SessionOptions) {\n const controller = new SessionProvider(options);\n\n super({\n options: {\n id: controller.id,\n name: controller.name,\n },\n });\n\n this.controller = controller;\n }\n\n async disconnect() {\n await this.controller.disconnect();\n try {\n await super.disconnect();\n } catch {\n // Best-effort: disconnect should not throw if the injected wallet isn't available.\n }\n }\n\n static fromConnectors(connectors: Connector[]): SessionConnector {\n const connector = connectors.find((c) => c.id === \"controller_session\");\n if (!connector) {\n throw new Error(\"Session connector not found\");\n }\n return connector as SessionConnector;\n }\n\n username() {\n return this.controller.username();\n }\n}\n"],"mappings":";AAAA,OAAO,wBAGA;AACP,SAAoB,yBAAyB;AAE7C,IAAqB,sBAArB,cAAiD,kBAAkB;AAAA,EAC1D;AAAA,EAEP,YAAY,UAA6B,CAAC,GAAG;AAC3C,QAAI;AAEJ,QAAI,OAAO,WAAW,eAAgB,OAAe,qBAAqB;AACxE,cAAQ;AAAA,QACN;AAAA,MAGF;AACA,mBAAc,OAAe;AAAA,IAC/B,OAAO;AACL,mBAAa,IAAI,mBAAmB,OAAO;AAAA,IAC7C;AAEA,UAAM,EAAE,SAAS,EAAE,IAAI,WAAW,IAAI,MAAM,WAAW,KAAK,EAAE,CAAC;AAC/D,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAM,aAAa;AACjB,UAAM,KAAK,WAAW,WAAW;AACjC,QAAI;AACF,YAAM,MAAM,WAAW;AAAA,IACzB,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,WAAW;AACT,WAAO,KAAK,WAAW,SAAS;AAAA,EAClC;AAAA,EAEA,UAAmB;AACjB,WAAO,KAAK,WAAW,QAAQ;AAAA,EACjC;AAAA,EAEA,MAAM,kBAAkB;AACtB,WAAO,MAAM,KAAK,WAAW,gBAAgB;AAAA,EAC/C;AAAA,EAEA,MAAM,QAAQ,MAAkD;AAC9D,UAAM,EAAE,aAAa,GAAG,eAAe,IAAI,QAAQ,CAAC;AACpD,UAAM,iBACJ,QAAQ,OAAO,KAAK,cAAc,EAAE,SAAS,IACxC,iBACD;AAEN,UAAM,UAAU,MAAM,KAAK,WAAW,QAAQ,cAAc;AAC5D,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAIA,QAAI,OAAO,WAAW,aAAa;AACjC,MAAC,OAAe,sBAAsB,KAAK;AAAA,IAC7C;AAEA,UAAM,OAAO,MAAM,MAAM,QAAQ,EAAE,YAAY,CAAC;AAKhD,WAAO,EAAE,GAAG,MAAM,SAAS,QAAQ,QAAQ;AAAA,EAC7C;AAAA,EAEA,OAAO,eAAe,YAA8C;AAClE,UAAM,YAAY,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY;AAC9D,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,mBAAmB;AACjB,WAAO,KAAK,WAAW,iBAAiB;AAAA,EAC1C;AACF;;;ACrFA,OAAO,qBAAyC;AAChD,SAAoB,qBAAAA,0BAAyB;AAE7C,IAAqB,mBAArB,cAA8CA,mBAAkB;AAAA,EACvD;AAAA,EAEP,YAAY,SAAyB;AACnC,UAAM,aAAa,IAAI,gBAAgB,OAAO;AAE9C,UAAM;AAAA,MACJ,SAAS;AAAA,QACP,IAAI,WAAW;AAAA,QACf,MAAM,WAAW;AAAA,MACnB;AAAA,IACF,CAAC;AAED,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAM,aAAa;AACjB,UAAM,KAAK,WAAW,WAAW;AACjC,QAAI;AACF,YAAM,MAAM,WAAW;AAAA,IACzB,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,OAAO,eAAe,YAA2C;AAC/D,UAAM,YAAY,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,oBAAoB;AACtE,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,WAAW;AACT,WAAO,KAAK,WAAW,SAAS;AAAA,EAClC;AACF;","names":["InjectedConnector"]}
|
package/dist/session.js
CHANGED
|
@@ -14,7 +14,11 @@ var SessionConnector = class extends InjectedConnector {
|
|
|
14
14
|
this.controller = controller;
|
|
15
15
|
}
|
|
16
16
|
async disconnect() {
|
|
17
|
-
this.controller.disconnect();
|
|
17
|
+
await this.controller.disconnect();
|
|
18
|
+
try {
|
|
19
|
+
await super.disconnect();
|
|
20
|
+
} catch {
|
|
21
|
+
}
|
|
18
22
|
}
|
|
19
23
|
static fromConnectors(connectors) {
|
|
20
24
|
const connector = connectors.find((c) => c.id === "controller_session");
|
package/dist/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/session.ts"],"sourcesContent":["import SessionProvider, { SessionOptions } from \"@cartridge/controller/session\";\nimport { Connector, InjectedConnector } from \"@starknet-react/core\";\n\nexport default class SessionConnector extends InjectedConnector {\n public controller: SessionProvider;\n\n constructor(options: SessionOptions) {\n const controller = new SessionProvider(options);\n\n super({\n options: {\n id: controller.id,\n name: controller.name,\n },\n });\n\n this.controller = controller;\n }\n\n async disconnect() {\n this.controller.disconnect();\n }\n\n static fromConnectors(connectors: Connector[]): SessionConnector {\n const connector = connectors.find((c) => c.id === \"controller_session\");\n if (!connector) {\n throw new Error(\"Session connector not found\");\n }\n return connector as SessionConnector;\n }\n\n username() {\n return this.controller.username();\n }\n}\n"],"mappings":";AAAA,OAAO,qBAAyC;AAChD,SAAoB,yBAAyB;AAE7C,IAAqB,mBAArB,cAA8C,kBAAkB;AAAA,EACvD;AAAA,EAEP,YAAY,SAAyB;AACnC,UAAM,aAAa,IAAI,gBAAgB,OAAO;AAE9C,UAAM;AAAA,MACJ,SAAS;AAAA,QACP,IAAI,WAAW;AAAA,QACf,MAAM,WAAW;AAAA,MACnB;AAAA,IACF,CAAC;AAED,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAM,aAAa;AACjB,
|
|
1
|
+
{"version":3,"sources":["../src/session.ts"],"sourcesContent":["import SessionProvider, { SessionOptions } from \"@cartridge/controller/session\";\nimport { Connector, InjectedConnector } from \"@starknet-react/core\";\n\nexport default class SessionConnector extends InjectedConnector {\n public controller: SessionProvider;\n\n constructor(options: SessionOptions) {\n const controller = new SessionProvider(options);\n\n super({\n options: {\n id: controller.id,\n name: controller.name,\n },\n });\n\n this.controller = controller;\n }\n\n async disconnect() {\n await this.controller.disconnect();\n try {\n await super.disconnect();\n } catch {\n // Best-effort: disconnect should not throw if the injected wallet isn't available.\n }\n }\n\n static fromConnectors(connectors: Connector[]): SessionConnector {\n const connector = connectors.find((c) => c.id === \"controller_session\");\n if (!connector) {\n throw new Error(\"Session connector not found\");\n }\n return connector as SessionConnector;\n }\n\n username() {\n return this.controller.username();\n }\n}\n"],"mappings":";AAAA,OAAO,qBAAyC;AAChD,SAAoB,yBAAyB;AAE7C,IAAqB,mBAArB,cAA8C,kBAAkB;AAAA,EACvD;AAAA,EAEP,YAAY,SAAyB;AACnC,UAAM,aAAa,IAAI,gBAAgB,OAAO;AAE9C,UAAM;AAAA,MACJ,SAAS;AAAA,QACP,IAAI,WAAW;AAAA,QACf,MAAM,WAAW;AAAA,MACnB;AAAA,IACF,CAAC;AAED,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAM,aAAa;AACjB,UAAM,KAAK,WAAW,WAAW;AACjC,QAAI;AACF,YAAM,MAAM,WAAW;AAAA,IACzB,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,OAAO,eAAe,YAA2C;AAC/D,UAAM,YAAY,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,oBAAoB;AACtE,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,WAAW;AACT,WAAO,KAAK,WAAW,SAAS;AAAA,EAClC;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cartridge/connector",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.6",
|
|
4
4
|
"description": "Cartridge Controller Connector",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -44,17 +44,20 @@
|
|
|
44
44
|
"@starknet-react/core": "^5.0.1"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@
|
|
48
|
-
"@cartridge/controller": "0.13.4"
|
|
47
|
+
"@cartridge/controller": "0.13.6"
|
|
49
48
|
},
|
|
50
49
|
"devDependencies": {
|
|
50
|
+
"@vitest/coverage-v8": "2.1.8",
|
|
51
51
|
"prettier": "^3.4.2",
|
|
52
52
|
"tsup": "^8.0.1",
|
|
53
53
|
"typescript": "^5.7.3",
|
|
54
|
-
"
|
|
54
|
+
"vitest": "2.1.8",
|
|
55
|
+
"@cartridge/tsconfig": "0.13.6"
|
|
55
56
|
},
|
|
56
57
|
"scripts": {
|
|
57
58
|
"build:deps": "tsup --dts-resolve",
|
|
59
|
+
"test": "vitest",
|
|
60
|
+
"test:ci": "vitest run",
|
|
58
61
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
59
62
|
"format:check": "prettier --check \"src/**/*.ts\""
|
|
60
63
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
// Mock starknet-react's InjectedConnector so we can control what super.connect returns.
|
|
4
|
+
vi.mock("@starknet-react/core", () => {
|
|
5
|
+
type InjectedConnectorOptions = { id: string; name?: string };
|
|
6
|
+
|
|
7
|
+
class InjectedConnector {
|
|
8
|
+
private readonly _options: InjectedConnectorOptions;
|
|
9
|
+
|
|
10
|
+
constructor({ options }: { options: InjectedConnectorOptions }) {
|
|
11
|
+
this._options = options;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get id(): string {
|
|
15
|
+
return this._options.id;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get name(): string {
|
|
19
|
+
return this._options.name ?? this._options.id;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Simulate an edge case where the injected request resolves but returns an
|
|
23
|
+
// empty/undefined account. Our connector should still return the address
|
|
24
|
+
// from controller.connect().
|
|
25
|
+
async connect(): Promise<{ account?: string; chainId?: bigint }> {
|
|
26
|
+
return { account: undefined, chainId: 1n };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async disconnect(): Promise<void> {}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// The real module exports both, but ControllerConnector only needs InjectedConnector.
|
|
33
|
+
class Connector {}
|
|
34
|
+
|
|
35
|
+
return { Connector, InjectedConnector };
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Mock controller SDK so ControllerConnector doesn't need a real iframe/keychain.
|
|
39
|
+
vi.mock("@cartridge/controller", () => {
|
|
40
|
+
class ControllerProvider {
|
|
41
|
+
id = "controller";
|
|
42
|
+
name = "Controller";
|
|
43
|
+
account?: { address: string };
|
|
44
|
+
|
|
45
|
+
constructor() {
|
|
46
|
+
if (typeof window !== "undefined") {
|
|
47
|
+
(window as any).starknet_controller = this;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async connect(): Promise<{ address: string } | undefined> {
|
|
52
|
+
this.account = { address: "0xabc" };
|
|
53
|
+
return this.account;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
disconnect() {}
|
|
57
|
+
username() {}
|
|
58
|
+
isReady() {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
delegateAccount() {}
|
|
62
|
+
asWalletStandard() {}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
__esModule: true,
|
|
67
|
+
default: ControllerProvider,
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
import ControllerConnector from "../controller";
|
|
72
|
+
|
|
73
|
+
describe("ControllerConnector", () => {
|
|
74
|
+
beforeEach(() => {
|
|
75
|
+
(globalThis as any).window = {};
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
afterEach(() => {
|
|
79
|
+
delete (globalThis as any).window;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("returns the address from controller.connect() even if injected connect has no account", async () => {
|
|
83
|
+
const connector = new ControllerConnector();
|
|
84
|
+
|
|
85
|
+
const result = await connector.connect();
|
|
86
|
+
|
|
87
|
+
expect(result.account).toBe("0xabc");
|
|
88
|
+
expect((window as any).starknet_controller).toBe(connector.controller);
|
|
89
|
+
});
|
|
90
|
+
});
|
package/src/controller.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import ControllerProvider, {
|
|
2
|
-
|
|
2
|
+
ConnectOptions,
|
|
3
3
|
ControllerOptions,
|
|
4
4
|
} from "@cartridge/controller";
|
|
5
5
|
import { Connector, InjectedConnector } from "@starknet-react/core";
|
|
6
6
|
|
|
7
|
-
import { StarknetInjectedWallet } from "@starknet-io/get-starknet-wallet-standard";
|
|
8
|
-
import type { WalletWithStarknetFeatures } from "@starknet-io/get-starknet-wallet-standard/features";
|
|
9
|
-
|
|
10
7
|
export default class ControllerConnector extends InjectedConnector {
|
|
11
8
|
public controller: ControllerProvider;
|
|
12
9
|
|
|
@@ -29,7 +26,12 @@ export default class ControllerConnector extends InjectedConnector {
|
|
|
29
26
|
}
|
|
30
27
|
|
|
31
28
|
async disconnect() {
|
|
32
|
-
this.controller.disconnect();
|
|
29
|
+
await this.controller.disconnect();
|
|
30
|
+
try {
|
|
31
|
+
await super.disconnect();
|
|
32
|
+
} catch {
|
|
33
|
+
// Best-effort: starknet-react may call disconnect even when the injected wallet isn't present.
|
|
34
|
+
}
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
username() {
|
|
@@ -44,12 +46,30 @@ export default class ControllerConnector extends InjectedConnector {
|
|
|
44
46
|
return await this.controller.delegateAccount();
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
async connect(args?: { chainIdHint?: bigint
|
|
48
|
-
const
|
|
49
|
+
async connect(args?: { chainIdHint?: bigint } & ConnectOptions) {
|
|
50
|
+
const { chainIdHint, ...connectOptions } = args ?? {};
|
|
51
|
+
const controllerArgs =
|
|
52
|
+
args && Object.keys(connectOptions).length > 0
|
|
53
|
+
? (connectOptions as ConnectOptions)
|
|
54
|
+
: undefined;
|
|
55
|
+
|
|
56
|
+
const account = await this.controller.connect(controllerArgs);
|
|
49
57
|
if (!account) {
|
|
50
58
|
throw new Error("Failed to connect controller");
|
|
51
59
|
}
|
|
52
|
-
|
|
60
|
+
|
|
61
|
+
// Ensure the injected wallet instance used by starknet-react (window.starknet_controller)
|
|
62
|
+
// always points at the same ControllerProvider instance this connector wraps.
|
|
63
|
+
if (typeof window !== "undefined") {
|
|
64
|
+
(window as any).starknet_controller = this.controller;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const data = await super.connect({ chainIdHint });
|
|
68
|
+
|
|
69
|
+
// `@starknet-react/core` updates its state from the `account` returned here.
|
|
70
|
+
// Use the authoritative address from `controller.connect()` to avoid edge cases
|
|
71
|
+
// where the injected wallet request returns an empty/undefined account.
|
|
72
|
+
return { ...data, account: account.address };
|
|
53
73
|
}
|
|
54
74
|
|
|
55
75
|
static fromConnectors(connectors: Connector[]): ControllerConnector {
|
|
@@ -60,14 +80,7 @@ export default class ControllerConnector extends InjectedConnector {
|
|
|
60
80
|
return connector as ControllerConnector;
|
|
61
81
|
}
|
|
62
82
|
|
|
63
|
-
asWalletStandard()
|
|
64
|
-
|
|
65
|
-
console.warn(
|
|
66
|
-
`Casting Controller to WalletWithStarknetFeatures is an experimental feature and may contain bugs. ` +
|
|
67
|
-
`Please report any issues at https://github.com/cartridge-gg/controller/issues`,
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return new StarknetInjectedWallet(this.controller);
|
|
83
|
+
asWalletStandard() {
|
|
84
|
+
return this.controller.asWalletStandard();
|
|
72
85
|
}
|
|
73
86
|
}
|
package/src/session.ts
CHANGED
|
@@ -18,7 +18,12 @@ export default class SessionConnector extends InjectedConnector {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
async disconnect() {
|
|
21
|
-
this.controller.disconnect();
|
|
21
|
+
await this.controller.disconnect();
|
|
22
|
+
try {
|
|
23
|
+
await super.disconnect();
|
|
24
|
+
} catch {
|
|
25
|
+
// Best-effort: disconnect should not throw if the injected wallet isn't available.
|
|
26
|
+
}
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
static fromConnectors(connectors: Connector[]): SessionConnector {
|