@cartridge/controller 0.5.7 → 0.5.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @cartridge/controller@0.5.7 build:deps /home/runner/work/controller/controller/packages/controller
2
+ > @cartridge/controller@0.5.8 build:deps /home/runner/work/controller/controller/packages/controller
3
3
  > tsup --dts-resolve
4
4
 
5
5
  CLI Building entry: src/account.ts, src/constants.ts, src/controller.ts, src/errors.ts, src/icon.ts, src/index.ts, src/lookup.ts, src/provider.ts, src/types.ts, src/utils.ts, src/iframe/base.ts, src/iframe/index.ts, src/iframe/keychain.ts, src/iframe/profile.ts, src/session/account.ts, src/session/backend.ts, src/session/index.ts, src/session/provider.ts, src/telegram/backend.ts, src/telegram/provider.ts
@@ -14,42 +14,42 @@
14
14
  ESM dist/session/account.js 2.25 KB
15
15
  ESM dist/telegram/backend.js 1.27 KB
16
16
  ESM dist/constants.js 247.00 B
17
- ESM dist/controller.js 34.25 KB
17
+ ESM dist/controller.js 36.30 KB
18
18
  ESM dist/errors.js 271.00 B
19
19
  ESM dist/icon.js 15.15 KB
20
+ ESM dist/index.js 260.41 KB
20
21
  ESM dist/lookup.js 1.59 KB
21
- ESM dist/provider.js 20.33 KB
22
- ESM dist/types.js 437.00 B
22
+ ESM dist/provider.js 20.52 KB
23
23
  ESM dist/utils.js 2.77 KB
24
+ ESM dist/types.js 437.00 B
24
25
  ESM dist/iframe/index.js 5.16 KB
25
- ESM dist/index.js 257.85 KB
26
26
  ESM dist/iframe/keychain.js 4.12 KB
27
27
  ESM dist/iframe/profile.js 4.69 KB
28
28
  ESM dist/session/backend.js 1.18 KB
29
- ESM dist/session/index.js 26.13 KB
30
- ESM dist/session/provider.js 25.52 KB
31
- ESM dist/telegram/provider.js 25.09 KB
32
- ESM dist/account.js.map 8.82 KB
29
+ ESM dist/session/index.js 26.51 KB
30
+ ESM dist/session/provider.js 25.91 KB
31
+ ESM dist/telegram/provider.js 25.46 KB
32
+ ESM dist/account.js.map 8.81 KB
33
33
  ESM dist/iframe/base.js.map 7.08 KB
34
34
  ESM dist/session/account.js.map 11.19 KB
35
35
  ESM dist/telegram/backend.js.map 1.98 KB
36
36
  ESM dist/constants.js.map 315.00 B
37
- ESM dist/controller.js.map 55.74 KB
37
+ ESM dist/controller.js.map 60.04 KB
38
38
  ESM dist/errors.js.map 385.00 B
39
- ESM dist/icon.js.map 15.20 KB
39
+ ESM dist/index.js.map 393.35 KB
40
40
  ESM dist/lookup.js.map 3.49 KB
41
- ESM dist/provider.js.map 24.59 KB
42
- ESM dist/types.js.map 4.75 KB
43
41
  ESM dist/utils.js.map 5.65 KB
42
+ ESM dist/types.js.map 4.75 KB
43
+ ESM dist/provider.js.map 25.41 KB
44
44
  ESM dist/iframe/index.js.map 10.47 KB
45
45
  ESM dist/iframe/keychain.js.map 8.27 KB
46
- ESM dist/iframe/profile.js.map 9.47 KB
47
46
  ESM dist/session/backend.js.map 2.88 KB
48
- ESM dist/session/index.js.map 42.29 KB
49
- ESM dist/session/provider.js.map 37.29 KB
50
- ESM dist/telegram/provider.js.map 36.46 KB
51
- ESM dist/index.js.map 388.38 KB
52
- ESM ⚡️ Build success in 119ms
47
+ ESM dist/iframe/profile.js.map 9.47 KB
48
+ ESM dist/session/index.js.map 43.61 KB
49
+ ESM dist/session/provider.js.map 38.61 KB
50
+ ESM dist/icon.js.map 15.20 KB
51
+ ESM dist/telegram/provider.js.map 37.76 KB
52
+ ESM ⚡️ Build success in 123ms
53
53
  DTS Build start
54
54
  ../tsconfig/base.json(6,25): error TS6046: Argument for '--moduleResolution' option must be: 'node', 'classic', 'node16', 'nodenext'.
55
55
 
@@ -93,26 +93,26 @@
93
93
 
94
94
  ../tsconfig/base.json(6,25): error TS6046: Argument for '--moduleResolution' option must be: 'node', 'classic', 'node16', 'nodenext'.
95
95
 
96
- DTS ⚡️ Build success in 8364ms
97
- DTS dist/index.d.ts 1.29 KB
98
- DTS dist/session/index.d.ts 739.00 B
99
- DTS dist/account.d.ts 1.63 KB
96
+ DTS ⚡️ Build success in 8227ms
97
+ DTS dist/index.d.ts 1.28 KB
98
+ DTS dist/session/index.d.ts 737.00 B
99
+ DTS dist/account.d.ts 1.64 KB
100
100
  DTS dist/constants.d.ts 215.00 B
101
101
  DTS dist/icon.d.ts 15.11 KB
102
- DTS dist/controller.d.ts 1.11 KB
102
+ DTS dist/controller.d.ts 1.34 KB
103
103
  DTS dist/lookup.d.ts 216.00 B
104
104
  DTS dist/utils.d.ts 725.00 B
105
105
  DTS dist/session/account.d.ts 1.83 KB
106
106
  DTS dist/errors.d.ts 100.00 B
107
- DTS dist/session/provider.d.ts 980.00 B
107
+ DTS dist/session/provider.d.ts 1.10 KB
108
108
  DTS dist/telegram/backend.d.ts 1.28 KB
109
109
  DTS dist/session/backend.d.ts 2.29 KB
110
- DTS dist/telegram/provider.d.ts 840.00 B
111
- DTS dist/provider.d.ts 775.00 B
110
+ DTS dist/telegram/provider.d.ts 975.00 B
111
+ DTS dist/provider.d.ts 897.00 B
112
112
  DTS dist/iframe/base.d.ts 184.00 B
113
113
  DTS dist/iframe/keychain.d.ts 172.00 B
114
114
  DTS dist/iframe/profile.d.ts 198.00 B
115
115
  DTS dist/iframe/index.d.ts 252.00 B
116
- DTS dist/types.d.ts 605.00 B
116
+ DTS dist/types.d.ts 603.00 B
117
117
  DTS dist/index.d-BbTUPBeO.d.ts 2.15 KB
118
- DTS dist/types-BReKRAuh.d.ts 6.22 KB
118
+ DTS dist/types-CVnDQVqD.d.ts 6.21 KB
@@ -1,12 +1,12 @@
1
1
 
2
- > @cartridge/controller@0.5.7 build /home/runner/work/controller/controller/packages/controller
2
+ > @cartridge/controller@0.5.8 build /home/runner/work/controller/controller/packages/controller
3
3
  > pnpm build:deps
4
4
 
5
5
 
6
- > @cartridge/controller@0.5.7 build:deps /home/runner/work/controller/controller/packages/controller
6
+ > @cartridge/controller@0.5.8 build:deps /home/runner/work/controller/controller/packages/controller
7
7
  > tsup --dts-resolve
8
8
 
9
- CLI Building entry: src/account.ts, src/constants.ts, src/controller.ts, src/errors.ts, src/icon.ts, src/index.ts, src/lookup.ts, src/provider.ts, src/types.ts, src/utils.ts, src/iframe/base.ts, src/iframe/index.ts, src/iframe/keychain.ts, src/iframe/profile.ts, src/session/account.ts, src/session/backend.ts, src/session/index.ts, src/session/provider.ts, src/telegram/backend.ts, src/telegram/provider.ts
9
+ CLI Building entry: src/account.ts, src/constants.ts, src/controller.ts, src/errors.ts, src/icon.ts, src/index.ts, src/lookup.ts, src/provider.ts, src/types.ts, src/utils.ts, src/iframe/base.ts, src/iframe/index.ts, src/iframe/keychain.ts, src/iframe/profile.ts, src/telegram/backend.ts, src/telegram/provider.ts, src/session/account.ts, src/session/backend.ts, src/session/index.ts, src/session/provider.ts
10
10
  CLI Using tsconfig: tsconfig.json
11
11
  CLI tsup v8.3.0
12
12
  CLI Using tsup config: /home/runner/work/controller/controller/packages/controller/package.json
@@ -15,45 +15,45 @@
15
15
  ESM Build start
16
16
  ESM dist/account.js 2.81 KB
17
17
  ESM dist/constants.js 247.00 B
18
- ESM dist/controller.js 34.25 KB
18
+ ESM dist/controller.js 36.30 KB
19
19
  ESM dist/errors.js 271.00 B
20
20
  ESM dist/icon.js 15.15 KB
21
- ESM dist/index.js 257.85 KB
21
+ ESM dist/index.js 260.41 KB
22
22
  ESM dist/lookup.js 1.59 KB
23
- ESM dist/provider.js 20.33 KB
23
+ ESM dist/provider.js 20.52 KB
24
24
  ESM dist/types.js 437.00 B
25
25
  ESM dist/utils.js 2.77 KB
26
26
  ESM dist/iframe/base.js 3.64 KB
27
27
  ESM dist/iframe/index.js 5.16 KB
28
28
  ESM dist/iframe/keychain.js 4.12 KB
29
29
  ESM dist/iframe/profile.js 4.69 KB
30
+ ESM dist/telegram/backend.js 1.27 KB
31
+ ESM dist/telegram/provider.js 25.46 KB
30
32
  ESM dist/session/account.js 2.25 KB
31
33
  ESM dist/session/backend.js 1.18 KB
32
- ESM dist/session/index.js 26.13 KB
33
- ESM dist/session/provider.js 25.52 KB
34
- ESM dist/telegram/backend.js 1.27 KB
35
- ESM dist/telegram/provider.js 25.09 KB
36
- ESM dist/account.js.map 8.82 KB
34
+ ESM dist/session/index.js 26.51 KB
35
+ ESM dist/session/provider.js 25.91 KB
36
+ ESM dist/account.js.map 8.81 KB
37
37
  ESM dist/constants.js.map 315.00 B
38
- ESM dist/controller.js.map 55.74 KB
38
+ ESM dist/controller.js.map 60.04 KB
39
39
  ESM dist/errors.js.map 385.00 B
40
40
  ESM dist/icon.js.map 15.20 KB
41
+ ESM dist/index.js.map 393.35 KB
41
42
  ESM dist/lookup.js.map 3.49 KB
42
- ESM dist/index.js.map 388.38 KB
43
- ESM dist/provider.js.map 24.59 KB
43
+ ESM dist/provider.js.map 25.41 KB
44
44
  ESM dist/types.js.map 4.75 KB
45
45
  ESM dist/utils.js.map 5.65 KB
46
46
  ESM dist/iframe/base.js.map 7.08 KB
47
47
  ESM dist/iframe/index.js.map 10.47 KB
48
48
  ESM dist/iframe/keychain.js.map 8.27 KB
49
49
  ESM dist/iframe/profile.js.map 9.47 KB
50
- ESM dist/session/account.js.map 11.19 KB
51
- ESM dist/session/backend.js.map 2.88 KB
52
- ESM dist/session/index.js.map 42.29 KB
53
- ESM dist/session/provider.js.map 37.29 KB
54
50
  ESM dist/telegram/backend.js.map 1.98 KB
55
- ESM dist/telegram/provider.js.map 36.46 KB
56
- ESM ⚡️ Build success in 139ms
51
+ ESM dist/telegram/provider.js.map 37.76 KB
52
+ ESM dist/session/backend.js.map 2.88 KB
53
+ ESM dist/session/index.js.map 43.61 KB
54
+ ESM dist/session/provider.js.map 38.61 KB
55
+ ESM dist/session/account.js.map 11.19 KB
56
+ ESM ⚡️ Build success in 172ms
57
57
  DTS Build start
58
58
  ../tsconfig/base.json(6,25): error TS6046: Argument for '--moduleResolution' option must be: 'node', 'classic', 'node16', 'nodenext'.
59
59
 
@@ -97,26 +97,26 @@
97
97
 
98
98
  ../tsconfig/base.json(6,25): error TS6046: Argument for '--moduleResolution' option must be: 'node', 'classic', 'node16', 'nodenext'.
99
99
 
100
- DTS ⚡️ Build success in 8231ms
101
- DTS dist/index.d.ts 1.29 KB
102
- DTS dist/session/index.d.ts 739.00 B
103
- DTS dist/account.d.ts 1.63 KB
100
+ DTS ⚡️ Build success in 8188ms
101
+ DTS dist/index.d.ts 1.28 KB
102
+ DTS dist/session/index.d.ts 737.00 B
103
+ DTS dist/account.d.ts 1.64 KB
104
104
  DTS dist/constants.d.ts 215.00 B
105
105
  DTS dist/icon.d.ts 15.11 KB
106
- DTS dist/controller.d.ts 1.11 KB
106
+ DTS dist/controller.d.ts 1.34 KB
107
107
  DTS dist/lookup.d.ts 216.00 B
108
108
  DTS dist/utils.d.ts 725.00 B
109
- DTS dist/session/account.d.ts 1.83 KB
110
- DTS dist/errors.d.ts 100.00 B
111
- DTS dist/session/provider.d.ts 980.00 B
112
109
  DTS dist/telegram/backend.d.ts 1.28 KB
110
+ DTS dist/telegram/provider.d.ts 975.00 B
111
+ DTS dist/session/account.d.ts 1.83 KB
113
112
  DTS dist/session/backend.d.ts 2.29 KB
114
- DTS dist/telegram/provider.d.ts 840.00 B
115
- DTS dist/provider.d.ts 775.00 B
113
+ DTS dist/errors.d.ts 100.00 B
114
+ DTS dist/session/provider.d.ts 1.10 KB
115
+ DTS dist/provider.d.ts 897.00 B
116
116
  DTS dist/iframe/base.d.ts 184.00 B
117
117
  DTS dist/iframe/keychain.d.ts 172.00 B
118
118
  DTS dist/iframe/profile.d.ts 198.00 B
119
119
  DTS dist/iframe/index.d.ts 252.00 B
120
- DTS dist/types.d.ts 605.00 B
120
+ DTS dist/types.d.ts 603.00 B
121
121
  DTS dist/index.d-BbTUPBeO.d.ts 2.15 KB
122
- DTS dist/types-BReKRAuh.d.ts 6.22 KB
122
+ DTS dist/types-CVnDQVqD.d.ts 6.21 KB
package/dist/account.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { WalletAccount, AllowArray, Call, InvokeFunctionResponse, TypedData } from 'starknet';
2
2
  import { SPEC } from '@starknet-io/types-js';
3
- import { K as Keychain, j as KeychainOptions, M as Modal } from './types-BReKRAuh.js';
3
+ import { K as Keychain, k as KeychainOptions, M as Modal } from './types-CVnDQVqD.js';
4
4
  import { AsyncMethodReturns } from '@cartridge/penpal';
5
5
  import BaseProvider from './provider.js';
6
6
  import './index.d-BbTUPBeO.js';
@@ -10,7 +10,7 @@ declare class ControllerAccount extends WalletAccount {
10
10
  private keychain;
11
11
  private modal;
12
12
  private options?;
13
- constructor(provider: BaseProvider, address: string, keychain: AsyncMethodReturns<Keychain>, options: KeychainOptions, modal: Modal);
13
+ constructor(provider: BaseProvider, rpcUrl: string, address: string, keychain: AsyncMethodReturns<Keychain>, options: KeychainOptions, modal: Modal);
14
14
  /**
15
15
  * Invoke execute function in account contract
16
16
  *
package/dist/account.js CHANGED
@@ -18,8 +18,8 @@ function toArray(val) {
18
18
 
19
19
  // src/account.ts
20
20
  var ControllerAccount = class extends WalletAccount {
21
- constructor(provider, address, keychain, options, modal) {
22
- super({ nodeUrl: provider.rpc.toString() }, provider);
21
+ constructor(provider, rpcUrl, address, keychain, options, modal) {
22
+ super({ nodeUrl: rpcUrl }, provider);
23
23
  this.address = address;
24
24
  this.keychain = keychain;
25
25
  this.options = options;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/account.ts","../src/utils.ts"],"sourcesContent":["import {\n InvokeFunctionResponse,\n TypedData,\n WalletAccount,\n Call,\n AllowArray,\n} from \"starknet\";\n\nimport { SPEC } from \"@starknet-io/types-js\";\n\nimport {\n ConnectError,\n Keychain,\n KeychainOptions,\n Modal,\n ResponseCodes,\n} from \"./types\";\nimport { AsyncMethodReturns } from \"@cartridge/penpal\";\nimport BaseProvider from \"./provider\";\nimport { toArray } from \"./utils\";\n\nclass ControllerAccount extends WalletAccount {\n address: string;\n private keychain: AsyncMethodReturns<Keychain>;\n private modal: Modal;\n private options?: KeychainOptions;\n\n constructor(\n provider: BaseProvider,\n address: string,\n keychain: AsyncMethodReturns<Keychain>,\n options: KeychainOptions,\n modal: Modal,\n ) {\n super({ nodeUrl: provider.rpc.toString() }, provider);\n\n this.address = address;\n this.keychain = keychain;\n this.options = options;\n this.modal = modal;\n }\n\n /**\n * Invoke execute function in account contract\n *\n * @param calls the invocation object or an array of them, containing:\n * - contractAddress - the address of the contract\n * - entrypoint - the entrypoint of the contract\n * - calldata - (defaults to []) the calldata\n * - signature - (defaults to []) the signature\n * @param abis (optional) the abi of the contract for better displaying\n *\n * @returns response from addTransaction\n */\n async execute(calls: AllowArray<Call>): Promise<InvokeFunctionResponse> {\n calls = toArray(calls);\n\n return new Promise(async (resolve, reject) => {\n const sessionExecute = await this.keychain.execute(\n calls,\n undefined,\n undefined,\n false,\n );\n\n // Session call succeeded\n if (sessionExecute.code === ResponseCodes.SUCCESS) {\n resolve(sessionExecute as InvokeFunctionResponse);\n return;\n }\n\n // Propagates session txn error back to caller\n if (this.options?.propagateSessionErrors) {\n reject((sessionExecute as ConnectError).error);\n return;\n }\n\n // Session call or Paymaster flow failed.\n // Session not avaialble, manual flow fallback\n this.modal.open();\n const manualExecute = await this.keychain.execute(\n calls,\n undefined,\n undefined,\n true,\n (sessionExecute as ConnectError).error,\n );\n\n // Manual call succeeded\n if (manualExecute.code === ResponseCodes.SUCCESS) {\n resolve(manualExecute as InvokeFunctionResponse);\n this.modal.close();\n return;\n }\n\n reject((manualExecute as ConnectError).error);\n return;\n });\n }\n\n /**\n * Sign an JSON object for off-chain usage with the starknet private key and return the signature\n * This adds a message prefix so it cant be interchanged with transactions\n *\n * @param json - JSON object to be signed\n * @returns the signature of the JSON object\n * @throws {Error} if the JSON object is not a valid JSON\n */\n async signMessage(typedData: TypedData): Promise<SPEC.SIGNATURE> {\n return new Promise(async (resolve, reject) => {\n const sessionSign = await this.keychain.signMessage(typedData, \"\", true);\n\n // Session sign succeeded\n if (!(\"code\" in sessionSign)) {\n resolve(sessionSign as SPEC.SIGNATURE);\n return;\n }\n\n // Session not avaialble, manual flow fallback\n this.modal.open();\n const manualSign = await this.keychain.signMessage(typedData, \"\", false);\n\n if (!(\"code\" in manualSign)) {\n resolve(manualSign as SPEC.SIGNATURE);\n } else {\n reject((manualSign as ConnectError).error);\n }\n this.modal.close();\n });\n }\n}\n\nexport default ControllerAccount;\n","import {\n addAddressPadding,\n Call,\n CallData,\n getChecksumAddress,\n hash,\n typedData,\n TypedDataRevision,\n} from \"starknet\";\nimport wasm from \"@cartridge/account-wasm/controller\";\nimport { Policies, SessionPolicies } from \"@cartridge/presets\";\n\n// Whitelist of allowed property names to prevent prototype pollution\nconst ALLOWED_PROPERTIES = new Set([\n \"contracts\",\n \"messages\",\n \"target\",\n \"method\",\n \"name\",\n \"description\",\n \"types\",\n \"domain\",\n \"primaryType\",\n]);\n\nfunction validatePropertyName(prop: string): void {\n if (!ALLOWED_PROPERTIES.has(prop)) {\n throw new Error(`Invalid property name: ${prop}`);\n }\n}\n\nfunction safeObjectAccess<T>(obj: any, prop: string): T {\n validatePropertyName(prop);\n return obj[prop];\n}\n\nexport function normalizeCalls(calls: Call | Call[]) {\n return toArray(calls).map((call) => {\n return {\n entrypoint: call.entrypoint,\n contractAddress: addAddressPadding(call.contractAddress),\n calldata: CallData.toHex(call.calldata),\n };\n });\n}\n\nexport function toSessionPolicies(policies: Policies): SessionPolicies {\n return Array.isArray(policies)\n ? policies.reduce<SessionPolicies>(\n (prev, p) => {\n if (safeObjectAccess<string>(p, \"target\")) {\n const target = getChecksumAddress(\n safeObjectAccess<string>(p, \"target\"),\n );\n const entrypoint = safeObjectAccess<string>(p, \"method\");\n const contracts = safeObjectAccess<Record<string, any>>(\n prev,\n \"contracts\",\n );\n const item = {\n name: humanizeString(entrypoint),\n entrypoint: entrypoint,\n description: safeObjectAccess<string>(p, \"description\"),\n };\n\n if (target in contracts) {\n const methods = toArray(contracts[target].methods);\n contracts[target] = {\n methods: [...methods, item],\n };\n } else {\n contracts[target] = {\n methods: [item],\n };\n }\n } else {\n const messages = safeObjectAccess<any[]>(prev, \"messages\");\n messages.push(p);\n }\n\n return prev;\n },\n { contracts: {}, messages: [] },\n )\n : policies;\n}\n\nexport function toWasmPolicies(policies: SessionPolicies): wasm.Policy[] {\n return [\n ...Object.entries(policies.contracts ?? {}).flatMap(\n ([target, { methods }]) =>\n toArray(methods).map((m) => ({\n target,\n method: m.entrypoint,\n })),\n ),\n ...(policies.messages ?? []).map((p) => {\n const domainHash = typedData.getStructHash(\n p.types,\n \"StarknetDomain\",\n p.domain,\n TypedDataRevision.ACTIVE,\n );\n const typeHash = typedData.getTypeHash(\n p.types,\n p.primaryType,\n TypedDataRevision.ACTIVE,\n );\n\n return {\n scope_hash: hash.computePoseidonHash(domainHash, typeHash),\n };\n }),\n ];\n}\n\nexport function toArray<T>(val: T | T[]): T[] {\n return Array.isArray(val) ? val : [val];\n}\n\nexport function humanizeString(str: string): string {\n return (\n str\n // Convert from camelCase or snake_case\n .replace(/([a-z])([A-Z])/g, \"$1 $2\") // camelCase to spaces\n .replace(/_/g, \" \") // snake_case to spaces\n .toLowerCase()\n // Capitalize first letter\n .replace(/^\\w/, (c) => c.toUpperCase())\n );\n}\n"],"mappings":";AAAA;AAAA,EAGE;AAAA,OAGK;;;ACNP;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA4GA,SAAS,QAAW,KAAmB;AAC5C,SAAO,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,GAAG;AACxC;;;ADjGA,IAAM,oBAAN,cAAgC,cAAc;AAAA,EAM5C,YACE,UACA,SACA,UACA,SACA,OACA;AACA,UAAM,EAAE,SAAS,SAAS,IAAI,SAAS,EAAE,GAAG,QAAQ;AAEpD,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,QAAQ,OAA0D;AACtE,YAAQ,QAAQ,KAAK;AAErB,WAAO,IAAI,QAAQ,OAAO,SAAS,WAAW;AAC5C,YAAM,iBAAiB,MAAM,KAAK,SAAS;AAAA,QACzC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAGA,UAAI,eAAe,kCAAgC;AACjD,gBAAQ,cAAwC;AAChD;AAAA,MACF;AAGA,UAAI,KAAK,SAAS,wBAAwB;AACxC,eAAQ,eAAgC,KAAK;AAC7C;AAAA,MACF;AAIA,WAAK,MAAM,KAAK;AAChB,YAAM,gBAAgB,MAAM,KAAK,SAAS;AAAA,QACxC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACC,eAAgC;AAAA,MACnC;AAGA,UAAI,cAAc,kCAAgC;AAChD,gBAAQ,aAAuC;AAC/C,aAAK,MAAM,MAAM;AACjB;AAAA,MACF;AAEA,aAAQ,cAA+B,KAAK;AAC5C;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,YAAYA,YAA+C;AAC/D,WAAO,IAAI,QAAQ,OAAO,SAAS,WAAW;AAC5C,YAAM,cAAc,MAAM,KAAK,SAAS,YAAYA,YAAW,IAAI,IAAI;AAGvE,UAAI,EAAE,UAAU,cAAc;AAC5B,gBAAQ,WAA6B;AACrC;AAAA,MACF;AAGA,WAAK,MAAM,KAAK;AAChB,YAAM,aAAa,MAAM,KAAK,SAAS,YAAYA,YAAW,IAAI,KAAK;AAEvE,UAAI,EAAE,UAAU,aAAa;AAC3B,gBAAQ,UAA4B;AAAA,MACtC,OAAO;AACL,eAAQ,WAA4B,KAAK;AAAA,MAC3C;AACA,WAAK,MAAM,MAAM;AAAA,IACnB,CAAC;AAAA,EACH;AACF;AAEA,IAAO,kBAAQ;","names":["typedData"]}
1
+ {"version":3,"sources":["../src/account.ts","../src/utils.ts"],"sourcesContent":["import {\n InvokeFunctionResponse,\n TypedData,\n WalletAccount,\n Call,\n AllowArray,\n} from \"starknet\";\n\nimport { SPEC } from \"@starknet-io/types-js\";\n\nimport {\n ConnectError,\n Keychain,\n KeychainOptions,\n Modal,\n ResponseCodes,\n} from \"./types\";\nimport { AsyncMethodReturns } from \"@cartridge/penpal\";\nimport BaseProvider from \"./provider\";\nimport { toArray } from \"./utils\";\n\nclass ControllerAccount extends WalletAccount {\n address: string;\n private keychain: AsyncMethodReturns<Keychain>;\n private modal: Modal;\n private options?: KeychainOptions;\n\n constructor(\n provider: BaseProvider,\n rpcUrl: string,\n address: string,\n keychain: AsyncMethodReturns<Keychain>,\n options: KeychainOptions,\n modal: Modal,\n ) {\n super({ nodeUrl: rpcUrl }, provider);\n\n this.address = address;\n this.keychain = keychain;\n this.options = options;\n this.modal = modal;\n }\n\n /**\n * Invoke execute function in account contract\n *\n * @param calls the invocation object or an array of them, containing:\n * - contractAddress - the address of the contract\n * - entrypoint - the entrypoint of the contract\n * - calldata - (defaults to []) the calldata\n * - signature - (defaults to []) the signature\n * @param abis (optional) the abi of the contract for better displaying\n *\n * @returns response from addTransaction\n */\n async execute(calls: AllowArray<Call>): Promise<InvokeFunctionResponse> {\n calls = toArray(calls);\n\n return new Promise(async (resolve, reject) => {\n const sessionExecute = await this.keychain.execute(\n calls,\n undefined,\n undefined,\n false,\n );\n\n // Session call succeeded\n if (sessionExecute.code === ResponseCodes.SUCCESS) {\n resolve(sessionExecute as InvokeFunctionResponse);\n return;\n }\n\n // Propagates session txn error back to caller\n if (this.options?.propagateSessionErrors) {\n reject((sessionExecute as ConnectError).error);\n return;\n }\n\n // Session call or Paymaster flow failed.\n // Session not avaialble, manual flow fallback\n this.modal.open();\n const manualExecute = await this.keychain.execute(\n calls,\n undefined,\n undefined,\n true,\n (sessionExecute as ConnectError).error,\n );\n\n // Manual call succeeded\n if (manualExecute.code === ResponseCodes.SUCCESS) {\n resolve(manualExecute as InvokeFunctionResponse);\n this.modal.close();\n return;\n }\n\n reject((manualExecute as ConnectError).error);\n return;\n });\n }\n\n /**\n * Sign an JSON object for off-chain usage with the starknet private key and return the signature\n * This adds a message prefix so it cant be interchanged with transactions\n *\n * @param json - JSON object to be signed\n * @returns the signature of the JSON object\n * @throws {Error} if the JSON object is not a valid JSON\n */\n async signMessage(typedData: TypedData): Promise<SPEC.SIGNATURE> {\n return new Promise(async (resolve, reject) => {\n const sessionSign = await this.keychain.signMessage(typedData, \"\", true);\n\n // Session sign succeeded\n if (!(\"code\" in sessionSign)) {\n resolve(sessionSign as SPEC.SIGNATURE);\n return;\n }\n\n // Session not avaialble, manual flow fallback\n this.modal.open();\n const manualSign = await this.keychain.signMessage(typedData, \"\", false);\n\n if (!(\"code\" in manualSign)) {\n resolve(manualSign as SPEC.SIGNATURE);\n } else {\n reject((manualSign as ConnectError).error);\n }\n this.modal.close();\n });\n }\n}\n\nexport default ControllerAccount;\n","import {\n addAddressPadding,\n Call,\n CallData,\n getChecksumAddress,\n hash,\n typedData,\n TypedDataRevision,\n} from \"starknet\";\nimport wasm from \"@cartridge/account-wasm/controller\";\nimport { Policies, SessionPolicies } from \"@cartridge/presets\";\n\n// Whitelist of allowed property names to prevent prototype pollution\nconst ALLOWED_PROPERTIES = new Set([\n \"contracts\",\n \"messages\",\n \"target\",\n \"method\",\n \"name\",\n \"description\",\n \"types\",\n \"domain\",\n \"primaryType\",\n]);\n\nfunction validatePropertyName(prop: string): void {\n if (!ALLOWED_PROPERTIES.has(prop)) {\n throw new Error(`Invalid property name: ${prop}`);\n }\n}\n\nfunction safeObjectAccess<T>(obj: any, prop: string): T {\n validatePropertyName(prop);\n return obj[prop];\n}\n\nexport function normalizeCalls(calls: Call | Call[]) {\n return toArray(calls).map((call) => {\n return {\n entrypoint: call.entrypoint,\n contractAddress: addAddressPadding(call.contractAddress),\n calldata: CallData.toHex(call.calldata),\n };\n });\n}\n\nexport function toSessionPolicies(policies: Policies): SessionPolicies {\n return Array.isArray(policies)\n ? policies.reduce<SessionPolicies>(\n (prev, p) => {\n if (safeObjectAccess<string>(p, \"target\")) {\n const target = getChecksumAddress(\n safeObjectAccess<string>(p, \"target\"),\n );\n const entrypoint = safeObjectAccess<string>(p, \"method\");\n const contracts = safeObjectAccess<Record<string, any>>(\n prev,\n \"contracts\",\n );\n const item = {\n name: humanizeString(entrypoint),\n entrypoint: entrypoint,\n description: safeObjectAccess<string>(p, \"description\"),\n };\n\n if (target in contracts) {\n const methods = toArray(contracts[target].methods);\n contracts[target] = {\n methods: [...methods, item],\n };\n } else {\n contracts[target] = {\n methods: [item],\n };\n }\n } else {\n const messages = safeObjectAccess<any[]>(prev, \"messages\");\n messages.push(p);\n }\n\n return prev;\n },\n { contracts: {}, messages: [] },\n )\n : policies;\n}\n\nexport function toWasmPolicies(policies: SessionPolicies): wasm.Policy[] {\n return [\n ...Object.entries(policies.contracts ?? {}).flatMap(\n ([target, { methods }]) =>\n toArray(methods).map((m) => ({\n target,\n method: m.entrypoint,\n })),\n ),\n ...(policies.messages ?? []).map((p) => {\n const domainHash = typedData.getStructHash(\n p.types,\n \"StarknetDomain\",\n p.domain,\n TypedDataRevision.ACTIVE,\n );\n const typeHash = typedData.getTypeHash(\n p.types,\n p.primaryType,\n TypedDataRevision.ACTIVE,\n );\n\n return {\n scope_hash: hash.computePoseidonHash(domainHash, typeHash),\n };\n }),\n ];\n}\n\nexport function toArray<T>(val: T | T[]): T[] {\n return Array.isArray(val) ? val : [val];\n}\n\nexport function humanizeString(str: string): string {\n return (\n str\n // Convert from camelCase or snake_case\n .replace(/([a-z])([A-Z])/g, \"$1 $2\") // camelCase to spaces\n .replace(/_/g, \" \") // snake_case to spaces\n .toLowerCase()\n // Capitalize first letter\n .replace(/^\\w/, (c) => c.toUpperCase())\n );\n}\n"],"mappings":";AAAA;AAAA,EAGE;AAAA,OAGK;;;ACNP;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA4GA,SAAS,QAAW,KAAmB;AAC5C,SAAO,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,GAAG;AACxC;;;ADjGA,IAAM,oBAAN,cAAgC,cAAc;AAAA,EAM5C,YACE,UACA,QACA,SACA,UACA,SACA,OACA;AACA,UAAM,EAAE,SAAS,OAAO,GAAG,QAAQ;AAEnC,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,QAAQ,OAA0D;AACtE,YAAQ,QAAQ,KAAK;AAErB,WAAO,IAAI,QAAQ,OAAO,SAAS,WAAW;AAC5C,YAAM,iBAAiB,MAAM,KAAK,SAAS;AAAA,QACzC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAGA,UAAI,eAAe,kCAAgC;AACjD,gBAAQ,cAAwC;AAChD;AAAA,MACF;AAGA,UAAI,KAAK,SAAS,wBAAwB;AACxC,eAAQ,eAAgC,KAAK;AAC7C;AAAA,MACF;AAIA,WAAK,MAAM,KAAK;AAChB,YAAM,gBAAgB,MAAM,KAAK,SAAS;AAAA,QACxC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACC,eAAgC;AAAA,MACnC;AAGA,UAAI,cAAc,kCAAgC;AAChD,gBAAQ,aAAuC;AAC/C,aAAK,MAAM,MAAM;AACjB;AAAA,MACF;AAEA,aAAQ,cAA+B,KAAK;AAC5C;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,YAAYA,YAA+C;AAC/D,WAAO,IAAI,QAAQ,OAAO,SAAS,WAAW;AAC5C,YAAM,cAAc,MAAM,KAAK,SAAS,YAAYA,YAAW,IAAI,IAAI;AAGvE,UAAI,EAAE,UAAU,cAAc;AAC5B,gBAAQ,WAA6B;AACrC;AAAA,MACF;AAGA,WAAK,MAAM,KAAK;AAChB,YAAM,aAAa,MAAM,KAAK,SAAS,YAAYA,YAAW,IAAI,KAAK;AAEvE,UAAI,EAAE,UAAU,aAAa;AAC3B,gBAAQ,UAA4B;AAAA,MACtC,OAAO;AACL,eAAQ,WAA4B,KAAK;AAAA,MAC3C;AACA,WAAK,MAAM,MAAM;AAAA,IACnB,CAAC;AAAA,EACH;AACF;AAEA,IAAO,kBAAQ;","names":["typedData"]}
@@ -1,8 +1,8 @@
1
- import { g as ControllerOptions, l as ProfileContextTypeVariant } from './types-BReKRAuh.js';
1
+ import { g as ControllerOptions, m as ProfileContextTypeVariant } from './types-CVnDQVqD.js';
2
2
  import BaseProvider from './provider.js';
3
3
  import { WalletAccount } from 'starknet';
4
4
  import { i as Policy } from './index.d-BbTUPBeO.js';
5
- import '@starknet-io/types-js';
5
+ import { AddStarknetChainParameters } from '@starknet-io/types-js';
6
6
  import '@cartridge/penpal';
7
7
 
8
8
  declare class ControllerProvider extends BaseProvider {
@@ -10,13 +10,18 @@ declare class ControllerProvider extends BaseProvider {
10
10
  private profile?;
11
11
  private options;
12
12
  private iframes;
13
+ private selectedChain;
14
+ private chains;
13
15
  constructor(options: ControllerOptions);
14
16
  probe(): Promise<WalletAccount | undefined>;
15
17
  connect(): Promise<WalletAccount | undefined>;
18
+ switchStarknetChain(chainId: string): Promise<boolean>;
19
+ addStarknetChain(_chain: AddStarknetChainParameters): Promise<boolean>;
16
20
  disconnect(): Promise<void>;
17
21
  openProfile(tab?: ProfileContextTypeVariant): Promise<void>;
18
22
  openSettings(): Promise<boolean | null>;
19
23
  revoke(origin: string, _policy: Policy[]): Promise<void> | null;
24
+ rpcUrl(): string;
20
25
  username(): Promise<string> | undefined;
21
26
  fetchControllers(contractAddresses: string[]): Promise<Record<string, string>>;
22
27
  openPurchaseCredits(): void;
@@ -18,8 +18,8 @@ function toArray(val) {
18
18
 
19
19
  // src/account.ts
20
20
  var ControllerAccount = class extends WalletAccount {
21
- constructor(provider, address, keychain, options, modal) {
22
- super({ nodeUrl: provider.rpc.toString() }, provider);
21
+ constructor(provider, rpcUrl, address, keychain, options, modal) {
22
+ super({ nodeUrl: rpcUrl }, provider);
23
23
  this.address = address;
24
24
  this.keychain = keychain;
25
25
  this.options = options;
@@ -294,7 +294,7 @@ import {
294
294
  // package.json
295
295
  var package_default = {
296
296
  name: "@cartridge/controller",
297
- version: "0.5.7",
297
+ version: "0.5.8",
298
298
  description: "Cartridge Controller",
299
299
  module: "dist/index.js",
300
300
  types: "dist/index.d.ts",
@@ -346,7 +346,7 @@ var icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AA
346
346
 
347
347
  // src/provider.ts
348
348
  var BaseProvider = class {
349
- constructor(options) {
349
+ constructor() {
350
350
  this.id = "controller";
351
351
  this.name = "Controller";
352
352
  this.version = package_default.version;
@@ -364,8 +364,9 @@ var BaseProvider = class {
364
364
  if (this.account) {
365
365
  return [this.account.address];
366
366
  }
367
+ const silentMode = call.params && call.params.silent_mode;
367
368
  this.account = await this.probe();
368
- if (!this.account) {
369
+ if (!this.account && !silentMode) {
369
370
  this.account = await this.connect();
370
371
  }
371
372
  if (this.account) {
@@ -379,24 +380,20 @@ var BaseProvider = class {
379
380
  message: "An unexpected error occurred",
380
381
  data: "wallet_watchAsset not implemented"
381
382
  };
382
- case "wallet_addStarknetChain":
383
- throw {
384
- code: 63,
385
- message: "An unexpected error occurred",
386
- data: "wallet_addStarknetChain not implemented"
387
- };
388
- case "wallet_switchStarknetChain":
389
- throw {
390
- code: 63,
391
- message: "An unexpected error occurred",
392
- data: "wallet_switchStarknetChain not implemented"
393
- };
383
+ case "wallet_addStarknetChain": {
384
+ let params2 = call.params;
385
+ return this.addStarknetChain(params2);
386
+ }
387
+ case "wallet_switchStarknetChain": {
388
+ let params2 = call.params;
389
+ return this.switchStarknetChain(params2.chainId);
390
+ }
394
391
  case "wallet_requestChainId":
395
392
  if (!this.account) {
396
393
  throw {
397
394
  code: 63,
398
395
  message: "An unexpected error occurred",
399
- data: "wallet_deploymentData not implemented"
396
+ data: "Account not initialized"
400
397
  };
401
398
  }
402
399
  return await this.account.getChainId();
@@ -411,7 +408,7 @@ var BaseProvider = class {
411
408
  throw {
412
409
  code: 63,
413
410
  message: "An unexpected error occurred",
414
- data: "wallet_deploymentData not implemented"
411
+ data: "Account not initialized"
415
412
  };
416
413
  }
417
414
  let params = call.params;
@@ -467,16 +464,60 @@ var BaseProvider = class {
467
464
  this.subscriptions.splice(idx, 1);
468
465
  }
469
466
  };
470
- const { rpc } = options;
471
- this.rpc = new URL(rpc);
467
+ }
468
+ emitNetworkChanged(chainId) {
469
+ this.subscriptions.filter((sub) => sub.type === "networkChanged").forEach((sub) => {
470
+ sub.handler(chainId);
471
+ });
472
+ }
473
+ emitAccountsChanged(accounts) {
474
+ this.subscriptions.filter((sub) => sub.type === "accountsChanged").forEach((sub) => {
475
+ sub.handler(accounts);
476
+ });
472
477
  }
473
478
  };
474
479
 
475
480
  // src/controller.ts
481
+ import { constants } from "starknet";
476
482
  var ControllerProvider = class extends BaseProvider {
477
483
  constructor(options) {
478
- const { rpc } = options;
479
- super({ rpc });
484
+ super();
485
+ const chains = /* @__PURE__ */ new Map();
486
+ for (const chain of options.chains) {
487
+ let chainId;
488
+ const url = new URL(chain.rpcUrl);
489
+ const parts = url.pathname.split("/");
490
+ if (parts.includes("starknet")) {
491
+ if (parts.includes("mainnet")) {
492
+ chainId = constants.StarknetChainId.SN_MAIN;
493
+ } else if (parts.includes("sepolia")) {
494
+ chainId = constants.StarknetChainId.SN_SEPOLIA;
495
+ }
496
+ } else if (parts.length >= 3) {
497
+ const projectName = parts[2];
498
+ if (parts.includes("katana")) {
499
+ chainId = `WP_${projectName.toUpperCase()}`;
500
+ } else if (parts.includes("mainnet")) {
501
+ chainId = `GG_${projectName.toUpperCase()}`;
502
+ }
503
+ }
504
+ if (!chainId) {
505
+ throw new Error(`Chain ${chain.rpcUrl} not supported`);
506
+ }
507
+ chains.set(chainId, chain);
508
+ }
509
+ if (options.policies?.messages?.length && options.policies.messages.length !== chains.size) {
510
+ console.warn(
511
+ "Each message policy is associated with a specific chain. The number of message policies does not match the number of chains specified - session message signing may not work on some chains."
512
+ );
513
+ }
514
+ this.chains = chains;
515
+ this.selectedChain = options.defaultChainId;
516
+ if (!this.chains.has(this.selectedChain)) {
517
+ throw new Error(
518
+ `Chain ${this.selectedChain} not found in configured chains`
519
+ );
520
+ }
480
521
  this.iframes = {
481
522
  keychain: new KeychainIFrame({
482
523
  ...options,
@@ -498,11 +539,10 @@ var ControllerProvider = class extends BaseProvider {
498
539
  console.error(new NotReadyToConnect().message);
499
540
  return;
500
541
  }
501
- const response = await this.keychain.probe(
502
- this.rpc.toString()
503
- );
542
+ const response = await this.keychain.probe(this.rpcUrl());
504
543
  this.account = new account_default(
505
544
  this,
545
+ this.rpcUrl(),
506
546
  response.address,
507
547
  this.keychain,
508
548
  this.options,
@@ -524,7 +564,7 @@ var ControllerProvider = class extends BaseProvider {
524
564
  openPurchaseCredits: () => this.openPurchaseCredits.bind(this),
525
565
  openExecute: () => this.openExecute.bind(this)
526
566
  },
527
- rpcUrl: this.rpc.toString(),
567
+ rpcUrl: this.rpcUrl(),
528
568
  username,
529
569
  version: this.version
530
570
  });
@@ -548,8 +588,8 @@ var ControllerProvider = class extends BaseProvider {
548
588
  this.iframes.keychain.open();
549
589
  try {
550
590
  let response = await this.keychain.connect(
551
- this.options.policies || [],
552
- this.rpc.toString()
591
+ this.options.policies || {},
592
+ this.rpcUrl()
553
593
  );
554
594
  if (response.code !== "SUCCESS" /* SUCCESS */) {
555
595
  throw new Error(response.message);
@@ -557,6 +597,7 @@ var ControllerProvider = class extends BaseProvider {
557
597
  response = response;
558
598
  this.account = new account_default(
559
599
  this,
600
+ this.rpcUrl(),
560
601
  response.address,
561
602
  this.keychain,
562
603
  this.options,
@@ -569,6 +610,23 @@ var ControllerProvider = class extends BaseProvider {
569
610
  this.iframes.keychain.close();
570
611
  }
571
612
  }
613
+ async switchStarknetChain(chainId) {
614
+ try {
615
+ this.selectedChain = chainId;
616
+ this.account = await this.probe();
617
+ if (!this.account) {
618
+ this.account = await this.connect();
619
+ }
620
+ } catch (e) {
621
+ console.error(e);
622
+ return false;
623
+ }
624
+ this.emitNetworkChanged(chainId);
625
+ return true;
626
+ }
627
+ addStarknetChain(_chain) {
628
+ return Promise.resolve(true);
629
+ }
572
630
  async disconnect() {
573
631
  if (!this.keychain) {
574
632
  console.error(new NotReadyToConnect().message);
@@ -621,6 +679,9 @@ var ControllerProvider = class extends BaseProvider {
621
679
  }
622
680
  return this.keychain.revoke(origin);
623
681
  }
682
+ rpcUrl() {
683
+ return this.chains.get(this.selectedChain).rpcUrl;
684
+ }
624
685
  username() {
625
686
  if (!this.keychain) {
626
687
  console.error(new NotReadyToConnect().message);