@cartridge/controller 0.5.6 → 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.
Files changed (43) hide show
  1. package/.turbo/turbo-build$colon$deps.log +31 -31
  2. package/.turbo/turbo-build.log +31 -31
  3. package/dist/account.d.ts +2 -2
  4. package/dist/account.js +2 -2
  5. package/dist/account.js.map +1 -1
  6. package/dist/controller.d.ts +7 -2
  7. package/dist/controller.js +140 -29
  8. package/dist/controller.js.map +1 -1
  9. package/dist/iframe/base.d.ts +1 -1
  10. package/dist/iframe/index.d.ts +1 -1
  11. package/dist/iframe/keychain.d.ts +1 -1
  12. package/dist/iframe/profile.d.ts +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.js +174 -47
  15. package/dist/index.js.map +1 -1
  16. package/dist/provider.d.ts +5 -6
  17. package/dist/provider.js +74 -19
  18. package/dist/provider.js.map +1 -1
  19. package/dist/session/account.d.ts +1 -1
  20. package/dist/session/account.js.map +1 -1
  21. package/dist/session/index.d.ts +1 -1
  22. package/dist/session/index.js +84 -22
  23. package/dist/session/index.js.map +1 -1
  24. package/dist/session/provider.d.ts +4 -3
  25. package/dist/session/provider.js +84 -22
  26. package/dist/session/provider.js.map +1 -1
  27. package/dist/telegram/backend.d.ts +1 -1
  28. package/dist/telegram/backend.js.map +1 -1
  29. package/dist/telegram/provider.d.ts +4 -3
  30. package/dist/telegram/provider.js +84 -24
  31. package/dist/telegram/provider.js.map +1 -1
  32. package/dist/{types-BReKRAuh.d.ts → types-CVnDQVqD.d.ts} +10 -11
  33. package/dist/types.d.ts +1 -1
  34. package/dist/types.js.map +1 -1
  35. package/package.json +3 -3
  36. package/src/account.ts +2 -1
  37. package/src/controller.ts +84 -9
  38. package/src/provider.ts +39 -24
  39. package/src/session/provider.ts +14 -4
  40. package/src/telegram/backend.ts +1 -1
  41. package/src/telegram/provider.ts +14 -5
  42. package/src/types.ts +11 -12
  43. package/tsconfig.json +2 -3
@@ -1,5 +1,5 @@
1
1
 
2
- > @cartridge/controller@0.5.6 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 33.08 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 19.16 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
26
  ESM dist/iframe/keychain.js 4.12 KB
26
27
  ESM dist/iframe/profile.js 4.69 KB
27
28
  ESM dist/session/backend.js 1.18 KB
28
- ESM dist/session/index.js 24.95 KB
29
- ESM dist/session/provider.js 24.35 KB
30
- ESM dist/telegram/provider.js 23.91 KB
31
- ESM dist/index.js 256.75 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 53.64 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 22.49 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 40.19 KB
49
- ESM dist/session/provider.js.map 35.19 KB
50
- ESM dist/telegram/provider.js.map 34.36 KB
51
- ESM dist/index.js.map 386.34 KB
52
- ESM ⚡️ Build success in 115ms
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 8658ms
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
- DTS dist/session/backend.d.ts 2.29 KB
107
106
  DTS dist/errors.d.ts 100.00 B
108
- DTS dist/session/provider.d.ts 980.00 B
109
- DTS dist/telegram/backend.d.ts 1.27 KB
110
- DTS dist/telegram/provider.d.ts 840.00 B
111
- DTS dist/provider.d.ts 775.00 B
107
+ DTS dist/session/provider.d.ts 1.10 KB
108
+ DTS dist/telegram/backend.d.ts 1.28 KB
109
+ DTS dist/session/backend.d.ts 2.29 KB
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.6 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.6 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 33.08 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 256.75 KB
21
+ ESM dist/index.js 260.41 KB
22
22
  ESM dist/lookup.js 1.59 KB
23
- ESM dist/provider.js 19.16 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 24.95 KB
33
- ESM dist/session/provider.js 24.35 KB
34
- ESM dist/telegram/backend.js 1.27 KB
35
- ESM dist/telegram/provider.js 23.91 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 53.64 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 386.34 KB
41
+ ESM dist/index.js.map 393.35 KB
42
42
  ESM dist/lookup.js.map 3.49 KB
43
- ESM dist/provider.js.map 22.49 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 40.19 KB
53
- ESM dist/session/provider.js.map 35.19 KB
54
50
  ESM dist/telegram/backend.js.map 1.98 KB
55
- ESM dist/telegram/provider.js.map 34.36 KB
56
- ESM ⚡️ Build success in 185ms
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 8311ms
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/telegram/backend.d.ts 1.28 KB
110
+ DTS dist/telegram/provider.d.ts 975.00 B
109
111
  DTS dist/session/account.d.ts 1.83 KB
110
112
  DTS dist/session/backend.d.ts 2.29 KB
111
113
  DTS dist/errors.d.ts 100.00 B
112
- DTS dist/session/provider.d.ts 980.00 B
113
- DTS dist/telegram/backend.d.ts 1.27 KB
114
- DTS dist/telegram/provider.d.ts 840.00 B
115
- DTS dist/provider.d.ts 775.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;
@@ -291,15 +291,65 @@ import {
291
291
  Permission
292
292
  } from "@starknet-io/types-js";
293
293
 
294
+ // package.json
295
+ var package_default = {
296
+ name: "@cartridge/controller",
297
+ version: "0.5.8",
298
+ description: "Cartridge Controller",
299
+ module: "dist/index.js",
300
+ types: "dist/index.d.ts",
301
+ type: "module",
302
+ scripts: {
303
+ "build:deps": "tsup --dts-resolve",
304
+ build: "pnpm build:deps",
305
+ format: 'prettier --write "src/**/*.ts"',
306
+ "format:check": 'prettier --check "src/**/*.ts"',
307
+ version: "pnpm pkg get version"
308
+ },
309
+ exports: {
310
+ ".": "./dist/index.js",
311
+ "./session": "./dist/session/index.js",
312
+ "./provider": "./dist/provider/index.js",
313
+ "./types": "./dist/types/index.js"
314
+ },
315
+ tsup: {
316
+ entry: [
317
+ "src/**"
318
+ ],
319
+ format: [
320
+ "esm"
321
+ ],
322
+ splitting: false,
323
+ sourcemap: true,
324
+ clean: true
325
+ },
326
+ dependencies: {
327
+ "@cartridge/account-wasm": "workspace:*",
328
+ "@cartridge/penpal": "^6.2.3",
329
+ "@starknet-io/types-js": "^0.7.7",
330
+ "@telegram-apps/sdk": "^2.4.0",
331
+ base64url: "^3.0.1",
332
+ "cbor-x": "^1.5.0",
333
+ "fast-deep-equal": "^3.1.3",
334
+ "query-string": "^7.1.1",
335
+ starknet: "^6.11.0"
336
+ },
337
+ devDependencies: {
338
+ "@cartridge/tsconfig": "workspace:*",
339
+ "@types/node": "^20.6.0",
340
+ typescript: "^5.4.5"
341
+ }
342
+ };
343
+
294
344
  // src/icon.ts
295
345
  var icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAABkyAAAZMgGvFqWRAAAAB3RJTUUH6AkEFwsj7EvbJQAAAAZiS0dEAP8A/wD/oL2nkwAAK45JREFUeNrt3XmUXVWBqPE42+3Qj5hQ995zb1WlUqkkVZlIAhnJPIKAIogICEGGtlugFVBaxAbsVgw+FWlooEFtRFAmZRbClDAlICAg4MTQDY4MAiIy6X5nX8JrQQippKruOef+vrW+Zf9hr2XOsPd3T52z96BBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgCWhpaRlWqVT2LFcq/5m6MvW+1EdTn08N3CCfX3sM7ysnydXpf56UHuNlpVKp3RUHAGjkpP+2dEL6aDox3WSyHljT4766lCQfSf/zb12JAIABobOz8y3pxHNIOhE9ZDJuuL8tVSoH9/T0vNmVCQDoN9KJf2Y66fzExJs570qSZJorFADQH5P/J9OJ5jmTbWb/LPBsKUkOdKUCAPqKN5TL5f8wyeYmBI5Lz9nrXbYAgI3hdemkcrKJNXee5NIFAGww6a/JI0ymGbFc7tV/v5Qkh7mCAQC9Jp1wFqcTyZ9Mvrn1T2nALXAlAwDWm8GDB7+zVKn8wiSaex8cMmTIO1zRAID1+/WfJF82eRbmpcCjXdEAgNekVqtV0onjaZNnYXxq6NChJVc2AGCdpL8Yl5s0C+fnXdkAgHXxxnSy+JUJs1jG9znSc/sGlzcA4NV+/S80YRbTliSZ5woHALwi6S/FL5gsC2qSfM4VDgB4RdKJ4jqTZWFd5QoHALxaADxqoiysD7nCAQB/RWtr6yYmyWIbF3hypQMAXkKpVGo3SRZ+UaBWVzoA4OUB0GOSLPjngKVStysdAPASWqrVsSbJgn8K2NIyxpUOABAAAgAAIAAEgAAAAAgACgAAgACgAAAACAAKAACAAKAAAAAIAAoAAIAAoAAAAAgACgAAgACgAAAACAAKAACAAKAAAAAIAAoAAIAAoAAAAAgACgAAgACgAAAACAABIAAAAAJAAAAAIAAEAABAAGTTreZ0hudu2iqTLp3dKQAAAAJAAAgAAIAAEAACAADQX7S2tm5SKpU2r1Qq25bL5X1Llcpn0oH/W6krXsv0/+cGAVDsAFh7jl/rWrg0vXZOqF875fI+a6+lye3t7f/HHQYADaZarQ5OB+YF6SB9cDlJTk3/79XpwP1w0V9iEwAN96F6RKTXXLz24jUYr0V3JAD0D69PkmR8+ivsn9IB+NzU+5v1LXYBkFnvr1+b5fIBaRCMS6/Z17ltAWDDfuF3pr+w/jH9pXV2/NXlEzYBkLcnBWkMnJVew/+waa023B0NAOugUqmMTCf8Q9PB81YTiAAomLemQfCpJEm63OkAsHbSjy9bpf95u0lCADSD6fV+WylJDovXvhEAQFPR3t7+1vTX0G7pYLjKhCAAmtyV6b2wa7wnjAwACkutVquUk+Rz6aD3iIFfAPAlPpzeG/82pK2tbKQAUKTH/BNTv5EOcs8Y6AUA1+kz8V6J94yRA0Au6enpeXMpSXZcu7CKgV0AsPf+IC5EVK1W/8aIAiAPv/Zr8VFmOnj9xgAuANgn/ibeU/HeMsIAyBqvS5JkfjpInZMOVs8ZsAUA+8Xn4j0W77VBFhoC0EgGDx78zvpiPZXKXQZnASAABtS74r0X70EjEYABo1QqdVcqlePSQegJA7EAEAAN9Yl4L8Z70sgEoL94Y7lcfl862FyZDjp/NvAKAAGQKf9cvzfTezTeq4YrABtNS0vLpunA8slm3oBHAAiAPJner78sVSpHJUlSNYIB6DXpL4lJ5SQ5MR1QnjKoCgABkNs1Bc6MWxYb0QCsk87OzrfEb/fTXw/XGzwFgAAolLfENQVaWlreZqQD8P+J25XGR4b15UgNlAJAABT5zwOP1Z/slcujjXxA8/L6+GgwPiJMB4bnDY4CQAA0lX+Kq3TGJ37pWPAGwyHQBGzS0fF38VGgb/cFgABg3SS5J77omzrECAkUkPTm3mztS31PGvQEgADgK/h0fCKYJMk0IyaQc2zIIwAEAG1EBDQRcU/xtd/uP2AgEwACgBuzEVH9BeFyuc3ICmT7Mf/Mtd/9PmvgEgACgH390mA6tmwzyEZEQEZ+7Q8Z8o74qC69MW83SAkAAcAB8CfxCWNra+smRmCgASRJ0rX22/1HDUgCQACwERsRxReLW6rVsUZkoP958dv9C2zIIwAEADPktfU1BSZNepNhGuhDbMhDAUAbEQFNhA15KABoIyKgSbAhDwUAbUQENNdj/o61L/U9ZMCgAKCNiIDmeKnPhjwUALQREVB0bMhDAUDWnwr8PL7gnCTJu8wMKDQ25KEAIG1EhCbBhjwUAKSNiNBE2JCHAoC0ERGaiLXf7p9qQx4KALJvXhqMq5+uXVPARkTI2K99G/JQAAgA2ogIzUO1Wh1hQx4KAAFAGxGhObAhDwWAAGDWNiIaNOiNpif0CzbkyZ8Tx7aFHZZ0hf13GxOWHzgxnP6FqeGKk7YMN5w6O9xyxpxc+uPvzstsAMT/bXk9rvGaiNdGvEbitRKvmXjtxGvIvZSvjYiq1WpixkJfvtRnQ56MW6slYZv5I8JRH9usPpD/+vJFmZ0omS/jtXT5iTPr19a7542oX2vuORsRoaC8uCFPeiFd52bKrh3DqmGfHbvDecdMD79btdhkxQExXmvfO2ZG2GuH0WFYe9W9mG1vXvuC9t+a2fBaj/ltyJMDt57bGc784rTw+DVLTEhsqI+tWhK+c/TU+rsZ7k0bESG/L/XZkCfjj/j3eX93WHPaHBMPM+ma02bXn0j5E4GNiJBx2tvb35pO+h9Nf/H/zE2RXcd1t4Uj99ss3H/xApMMc+EvLlsYvnrIJC8QZtw49sc5IM4FZsTm4Q3pSV9mid5su2hWZ/ivf90iPHn9UpMKc+lTNywN3/3K9LDj0pHu6Wz7QJwTPBEoOPFRf3qyf+iCz6ZtbUnYb5eecNuZc00gLJR3nzsvHLrv+DC8w0uDGfautX8aQJGoVqvjyuXyVS7wbDp1Ynv9kelvr/TpHovtIyuX1J9szZrS4d7PqulcYYXBgnzOl/7qP9LGPNkzqSb1R6PxEenTazzmZ3P5THrNX3XylmHvHbtDteqlwQx+NfBs6hFxDjGT5pAkSaalJ/JOF3O2HNlZDQcuG1d/JGoiILcK91wwv/6ia8+oVmNE9ryzJUmmmlHzwxvTclu+9nMPF3BGXDBzeP3Rp2/3yVf2D9e/8NLg1nNHGDMy9ulgXB9mkL0GMv+3/iQ9Wde4YLNha2tSf8QZH3Ua4Mn1N+5PEJ+UWWkwU66q1WoVM20GKVWrc9IT9CsXaeOd0NNaf6T5wKULDebkRvirFYvqL8huPqHd2JINHyqXy4vNuNn6vO8TVvFrvNsuGFF/hPnH1V7qI/vjpcHdthsVKomxpsE+X6pUDjbzNp7XpZP/0S7IxjlieK3+qPKOs73URw6EPz3vhZcGR3XVjEGNXUnw2HQOer1puAHE5RvLSXK2C7ExTp88rP5o8uGr7MJHNmpXwvhi7dxp1hRomOkcZCnhAWbw4MHvjC9kuAAH/tv9+AgyPop89kYDMJmllwbjKpqtNeNUI14OjHOSmXlg/t7/t2l1Xe2iGzjHdr/wUt99F9mQh8yyD162yEZEjflzwPVDhw59uxm6fz/z+5s0AK5wwQ3shjy/v863+6SNiPgaEXB5nKPM1P1AT0/Pm9PJ/0IXWv9vyBO/3Y97mxtIyfz7w+/Mrb+oayOiAfFSywf3w9v+6YH9lour/5wy8YWX+n5zhQ15yCJvRLSljYj6+8XAb8Y5y7TdR6QH9FAXlg15SNqIKCc7Cv6zmbsvJv9y+b3W9bchD0kbEeXIP5eS5P1m8I176W9ceiCfdDHZkIekjYhy5pNxDjOTb+jnfpXK3S4iG/KQtBFRTr0rzmVm9N4++q9UTnLxbPyGPP/zfRvykLQRUQPfBzjBjN77v/u7cDbw2/1vL58anlptACPZNy8NXnL8zPoLwzYi2sA1ArwPsH4MaWsrpwfsEReNDXlI2ogoJ7/yX+u/88jQoUNLZvjXoFSpnOGCWj+nTbIhD0kbEeXEb5nh1/3i3wIXyfp9ux8fydmQh2SjveHU2fUXjWs1awq8lnGOM9O/ylK/3vq3IQ/JfG9EtNkYGxGtY7+An9k++JVf/PuUC8SGPCRtRFTwpYIPNeP/Ba2trZukB+ZRF8dLN+RZ/U0b8pDMr7d+e46NiP76zwCPJUnyLjP///7tf7kLw4Y8JG1E1CR/CjjKzJ9Sq9Uq6QF5yoY8NuQhaSOiJvEPce7z679S+fdmvAC6Ol/4dv8uG/KQbEJ/fsGC+ovN3SNbm/UpwFebfbOfwc222U98BHbSZza3IQ9Jrt2IKK5eOn/G8KZ7CtDU7wI0y5v/cUOev/9AT/172Q29SX5w+pyw5/u6w+Tx7fbwJpm5P2VOGtcWdn/v6LDmtA0f5+IYGcfKOGY2yQuBn2zO2X/SpDelB+CBIp/c+D3sFw+aFH5x2cZtyHPpCVs2zQ1BMuc/eGqVcMGx0zdqzItjZhw7m2BNgf+Jc2Ez/u3/A0U9qdsv6grfO2ZG+OPqjX+pL35TO8HCGiRzZM+o1vDEtRv/Z844hsaxNI6pBX4KsFMzbvd7WdE25PnEh8eGO8/p25f64q9/AwrJvHneMdP7dCyMY2scY+NYW7BjdUkzfvr3fFG+3T/58C3Coyv7Z0Oe4w7d3GBCMncefdDEfhkT41gbx9w49hbkWD0fd8Ftph3/Dsr7SesYVg3LD5wYnry+f7/d//InJhlMSObOzx2wWf8uObx6q/oXVZ3DC7DKYJJ8vJkC4LY8n6xl23eH/75k4YB8IiMASAqAV/f+ixfUvz7I+fG6tSkm/5aWlo7cvqyRVOq/+gdyG14BQFIArNs4Jsdl1JMcfyK9aa02vBm+/T8gjycnPma68NgZA75IhgAgKQDWz8tOmBlGdubzTwKVSmU/b/9ndPKPC/E0YpUsAUBSAKy/N6VjdU53H/x+0R//vy39Rz6dt0UtVpw4s2HLZAoAkgKgd159yqw8Lp729NChQ99e3Jf/SqWlebuIz/zitIauky0ASAqA3nvG8mn5O27l8pIir/53ZJ5Oxj/tPrbhG2UIAJICYMPcf9cxeXsP4IgiB8AVeTkRcfndh69aLABIMqcB8MjKJfVNinJ03C4r6vz/hvQf90ReTkR8mzQLW2UKAJICYOO+DMjRcXs8zpXFewGwWh2bl5PwvsVdmdkrWwCQFAAbZ542EyqVSj12/2ug8Q1SAUCSxQiAq07Oz6ZqpSTZsYgBcMQ63nzMzMHfeu6IzFy0AoCkAOgbt57bmZcAOKyIAfCdPBz8+OmIACDJYgXA6UdNzcuxO90GQA1a9CcLb/4LAJICoI+/CLh6cV4WByrexkDpP+rRrB/4XbYZmakLVgCQFAB95wfePSoPx+7hQk3+7e3tb83DBXvKkVsIAJIsaACcfPgWeTh2f+7p6XlzkZYAbs/DBXtTgzb8EQAkBUD/u+a02XlZEbBWnDUAkmRq1g94tZqEJ65dIgBIsqABEMf4ONbnYC2AzYvz9/9yeUnWD/isKR2Zu1gFAEkB0LfO3KIj+8evXF5cpAB4b9YP+E5bjxQAJFnwANhhSfZXBaxUKtsWaQ2AnbN+wPfesVsAkGTBA+DDO3TnIQB2KlIALMv6Af/4HmMFAEkWPADiNu85WA1w9yL9CWCfrB/wT//9eAFAkgUPgDjW5+AdgH2KFAD7Zv2AHyYAuJ6O7qqF2VM7wtSJ7WFYe9UxIXMUAIflIwD2FQACQABkxOEd1fBv6YB25znzXnJ+nrphabj8xJnhQ+8Z7TiRAkAACAABUCS3XTAiPHDpwtc8V1ectGUY1VVzzEgBIAAEgADIux/cZlT4/XXrv0DUXefOC+N72hw7CgABIAAEgADIq0tnd4bHr+n96pB3nD3PkwAKAAEgAASAAMijUye1h1+tWLRRa453DPOCIAWAABAAAkAA5MYJY9rCvRct2Ohzd8nxM0OtljimFAACQAAIAAGQdbs6a+G2M+f22fn79vKpoZI4rhQAAkAACAABkFlbW5Nw5X9u2efn8JhPOocUAAJAAAgAAZBJk2oSvvuV6f12Hv/lH8Y7zhQAAkAACAABkDVPOGxyv57HZ2/cKuy/2xjHmgJAAAgAASAAsuJn9x+YgerpNUvDsu27HXMKAAEgAASAAGi0H9m5p/7rfKDOZ1xUaLuFXY49BYAAEAACQAA0yh2WdNXX8h/oc/rIyiVh/ozhzgEFgAAQAAJAAAy0i2d1hsdWLWnYeX3w0oVh8wntzgUFgAAQAAJAAAzYKn8T28MvVyxs+Ln9+fkLwrhu+wZQAAgAASAABEC/O2Z0a/jZ+fMzc35vP2tuGDnCvgEUAAJAAAgAAdBvjhheC7d+e07mzvHKr80KbW2WDKYAEAACQAAIgL5f5a9WCZefODOT5zh64bEzQrUqAigABIAAEAACoM+Ma/GfsXxaZif/F/3GZ7dwvigABIAAEAACoK88/tObZ37yf9GjD5ronFEACAABIAAEwMZ6yF7jcjP5v+g/7T7WuWugc6d1hC+l992lJ2wZbjp9TrjljMZ4c+qKE2fWA3bruSMEgAAQAAKA6+u86cPDU6u3yl0A/OH6pWHmFh3OYQNeEo3bNw/kypC9MQZJnj4bFQACQAAIgIb5/f+YmbvJ/0XjzoTO4QC+JNqahOu+MSvz18Xd587LzWejAkAACAAB0BDH97TVN9/JawDEJYqtDzBwHvHRCbm5Nk4+YgsBIAAEgADgq7n7e0fndvJ/0fdvNdK5HCB/et783FwXv1u1uP7EQgAIAAEgAPgKHrzn2NwHwEd3GeNcDtAaEc/k7GlRXM5aAAgAASAA+Aruv9uY3AfA3jt2O5cD4PCOau6ujTnThgsAASAABABfyW3mj8h9AMSvGJxLASAABIAAEADs5VvdD121OLeT/4OXLbI0sAAQAAJAAAgAg/SG+NVDJuU2AL7wMSsCCgABIAAEgAAwSG+Q8TO6+y9ekLvBPW5XHCcl51AACAABIAAEADfQRbM6wyMrl+RmYP/tlYtyMbgLAAEgAASAABAAmTcOlneeMy/zg/ptZ84N0ycPc84EgAAQAAJAAAiAvrJWS8L+u44JV58yKzxxbXaeCDy2akm44qQtw0d27vHSnwAQAAJAAAgAAdDv7wd0VsOorlpD7eq01K8AEAACQAAIAAFACgABIAAEgAAQAKQAEAACQAAIAJICQAAIAAEgAEgKAAEgAASAACApAASAABAAAoCkABAAAkAACIDcOntqRzj6oInhkuNnhjWnzQkrTpwZjv3nyeHd80aYuFKTahJ2WNIVTjhscn0tgXiMLvr3GfWBNw/7xQsAASAABIAAEAAvcVx3W/jeMTPWeVxWf3N2mDu9o2knrW0XjAh3nPXqqxs+s2Zp+Nbnp9bXOzDJCwABIAAEgADIvPNnDA8PXLpwvY7Nk9cvDcu27266Cevje4wNT6cT/Poco5+eNz9MneRpgAAQAAJAAAiADLv9oq5eb9zz1A1Lw9ZzO5vmGO227aj6r/veHKNfrlgYFm7ZabIXAAJAAAgAAZA94y/5+It+Q47RXefOq6/1X/Rj1Dm8Gh5cz6cjL/fRlYvr7wuY8AWAABAAAkAAZMYDl41b70far+Ye248u/HE6eM+xG3WM/pAG1l47jDbpCwABIAAEgABovEfut1l49saNP06nHzW18BNV/ApiY49TDK0YEiZ+ASAABIAAEAAN+4Tt5MO36LPjdMsZcwo/UT2wgY//X8nlH59o8hcAAkAACAABMLC2tibh3C9P79PjdO+F8ws/UT1+zZI+PWZfO3JKPcSsp5DUXybNUwBMGNMmAASAABAA+fu11RePsl/ufRctKPxE9fvrlvT5cbvw2BmhvU0E3HDq7NxM/vem13olqQgAASAABEB+HN1VC2tO65+BVgBsuKu+Pit0ddaaOgB2f+/o3ATAJz6cj3c4BIAAEAACoO7mE9rDT743v9+OkwDYOO84e14uHiv3p8d8clLmJ//TvzA1N3+2EQACQAAIgPqa/v/z/YX9epwEQN+8R9Hsqwbuu1NP/ThkbRx48LJF9a838vDoXwAIAAEgAOpuNacz/PbKRf1+nARA3/iLyxbWl2Nu5giopr+wt547ov6oPX6m2kgP2XtcfYXM+OJs3o6jABAAAqCJA2C37UYNyKQlAPrWx1YtCTsuHekTQQoAASAABEDv3W+XnvDU6oE7TgKgb42rBu69Y7eJjAJAAAgAAbD+Hrrv+D5Z3U8ANC4AXlw18KBlVg2kABAAAkAAvIbxBaVjPzW5IcdJAPSfXz1kkgmNAkAACAAB8OovTn3n6KkNO04CoH894bDJJjUKAAEgAATAX3vKkVs09DgJgP73qI9tZmKjABAAAkAA/MXb/tuOavhxEgD9b3yvY8nsTpMbBYAAEAAC4AVvP2uuAGiCAIhefuJMkxsFgAAQAAKgEqZPHpaJ4yQABu7LgJ5RrSY4CgABIACaPQD233WMAGiiAIju/O5RJjgKAAEgAJo9AOJypQKguQIgRp8JjgJAAAiAJg+AQ/YaJwCaLAD2fJ8VAikABIAAaPoA+MC7RwmAJguAudM7THAUAAJAADR7ALS1JeHRlYsFQJMEwL3pcc7TlrQUAAJAAAiAfvTYf54sAJokAOI+DyY3CgABIAAEQN2uzlq498L5AqDgAfDD78wNrTUTGwWAABAAAuBl6wH8+vJFAqCgARAf/U8Y02ZiowAQAAJAAPy1Uye2h5+fv0AAFCwA7jp3Xpg8vt2kRgEgAASAAHh1x/e0hVu/PUcAFCQA1pw2O3SPtPIfBYAAEAACYD3sHF4NK06cKQByHgAXHjsjDGuvmswoAASAABAA629raxLO/OI0AZDTADj58C1CUk1MZBQAAkAACIDeG78XX37gRAGQowCIW/7Gc2YCowAQAAJAAGy0n9p3fHhmzVIBkPEA+OPqpeFje4w1eVEACAABIAD6zmXbd4cnr18qADIaAI9fsyR8cBu7/FEACAABIAD6we0XdYVHrl4sADIWAL9csTAsmtVp0voLR3XVwnsWdtU3Ptp7x8a41w6j6/fMuO42ASAABIAAyL+zp3aE/75koQDISADcc8H8MG3SMJP+WhfMHB4uPWHL8HQ//8mqt+9lXPeNWfUYEAACQAAIgFwbF5WJi8v09Up1RZ+cnri2bwPgptPnhDGjfeP/ov/4wTHhqRuWZnIciMb3aI7cbzMBIAAEgADIt6O7auGGU2f32XG67cy5hZ+gHrys75Zajr9yh3f4xv9FF8/qrL8EmdXJ/y/d/b2jBYAAEAACIN/GrYTP/cr0PjlOZ31xWuEnqZVfm9Unx+r0L0y1qc/LvOT4mbmY/KN3nD1PAAgAASAA8m+1moSvHTllo49TfHxb9Enq8H+YsNHH6f8ePKm+PoNJ/6XGryDyEgDRPPzpRgAIAAEgANZ7sIgvO23IMbr/4gWhva34q9bFNfk39CuK+FLbwXv6xv+V7BhWzdXkH40v0woAASAABEBh3H/XMb3+O2x8MWrXbZvn+/UDPjSm19dQ/Hpgj+1Hm+xfxfguRN4CYM604QJAAAgAAVAs42I0j61ast6fRx2y17imm7C+eNCk9b5+fnvlorDN/BEmegEgAASAABAA2XfLKR31T9Re67O/D7y7eVeu22fH7vCLy9a9nsLVp8yqf3JpkhcAAkAACAABkKuNhHbZZmT9jfUfnT23vtDP3efOC+d8aVr4yM499d0GTVzV+p8ELjh2evjxd+fVj9HtZ80N//WvW+Ru0RgBIAAEgAAQAAKAFAACQAAIAAEgAEgBIAAEgAAQACQFgAAQAAJAAJAUAAJAAAgAAUBSAAgAASAABABJASAABIAAEAD8iyV141oDi2Z1NtT4v2FUV805EQACQAAIAAEgAPrLrs5afUCK38tn6fzG1QzvPGdeOOKjE2zPKwAEgAAQAAJAAPSlcVGcBy9blPlB/b8vWRi2nmvZXgEgAASAABAAAmCjff9WI8Mfrl+am4E9btyz3UKr+AkAASAABIAAEAAb7ISe1vpmOHkb3OPTiviegnMoAASAABAAAoAb4NeOnJK7gf1Fjzt0c+dQAAgAASAABIBBurd2DKuu97bCWfShqxbb8EgACAABIAAEgEG6t75vcVduJ/8XXTq707kUAAJAAAgAAcDe+PE9xuY+APbdqce5FAACQAAIAAHA3njQsvwHwD9+cIxzKQAEgAAQAAKAvXGXbUbmPgDi+gXOpQAQAAJAAAgA9sLRXbXw1A1Lczv5P3HtEisDCgABIAAEgAAwSG+I53xpWm4D4Fufn+ocDpBtbUnuro8Zmw8TAAJAAAgAvppTJ7aHx6/J36eAj65cHCaNa3MOB9AHL12Ym+sjPtmKn7kKAAEgAAQA12F8kz5uuJOXwf2ZNUvDsu27nbsB9vhPb56ba+TcL0/PxTEVAAJAAAiAhht32svL4P7pPAxOBXTkiFq454L5mb8+fn35ojB5fLsAEAACQABwff2Pw7L/C2/5gROdqwa6+YT28IPT52T2+ohbWc+d1pGb4ykABIAAEACZsJJUwreXT83s4P71z05xnjJgtZqEfd7fHS44dnq496IF4eGrFjfUuEX0pSdsGQ740JjcLQ0tAASAABAAmbG1VglX/ueWmTvHFx47oz7xOEcskgJAAAgAAZApuzpr4YffmZuZ87vya7Pqn6E5NxQAAkAACAAB0M+O7W4NPz9/QcPP7c1nzAkjhtecEwoAASAABIAAGLA1Aia1h1+tWNSw8xoDZFy3b/0pAASAABAAAmDAXTK7Mzy2auAXCoqLzsQ3zp0DCgABIAAEgABo4KZBf1w9cHsGPLJySZg3fbhjTwEgAASAABAAjTZuuzsQqwX+/rolYdsFIxxzCgABIAAEgABolsHqqdVb1Z82ONZ0TwkAASAABEDGPPEz/bNaYHy6sP+uYxxjCgABIAAEgADIokk1Cd/9yvQ+P4ef+Yj1/SkABIAAEAACINurBbYm4aqTt3T+SAEgAASAAGjG1QJvP2vjVws8Y/m0+h4EjikFgAAQAAJAAOTECWPawn0XbfhqgRcfNyPUapb4pQAQAAJAAAiA3DlrSkd46KrFvT5nq74+K7Rb358CQAAIAAEgAPLr1nM7exUBN5w6O4zsrDp2FAACQAAIAAFQhCcBr/VOQPzU7/SjpvrlTwoAASAABECRrFaTsN8uPWHFiTPD49csecm6/qd9bkp9XwHHiRQAAkAACICCG7fxbfNrnxQAAkAACACSFAACQAAIAJICQAAIAAEgAEgKAAEgAASAACApAASAABAAAoCkABAAAkAACACSAkAACAABIABICgABIAAEAEkKAAEgAAQASQoAASAABABJCgABIAAEAEkKAAEgAAQASQoAASAABABJCgABIAAEAEkKAAEgAAQASQoAASAABABJCgABIAAEAEkKAAFQiAD4tAAgycIHwKcFwIAHwD5ZP+CH7D1OAJBkwQPgkL3G5SEA9ilSAOyd9QN+0LKxAoAkCx4ABy7LfgBUKpW9ChMA6T/mw1k/4Ad8aIwAIMmCB8D+u43JQwDsWaQnALtl/YDvvWO3ACDJggfAXjuMzsOfAHYp0hOA92T9gG+3sCuTF+u/HzrZYEIydy4/cGImx9Rt5o/IwxOAbQoTAC1JMi/rB3zM6NZMXqwXHzfDYEIyd5775emZHFN7RrVm/tiVSqXZRfoTwOQ8XLD3X7wgcxfr769bkosLliRftKuzFn63anHmxtP7LlqQi+NXqVQmFulPAK15OOhf/+yUTBbrOV+aFpJqYmAhmf3JK6mE078wNZNjaRzj83AMkySpDioQb0gj4NmsH/T3Lc7mewDRFSfODFvPHRFaW4UAyewZx6alszvDJcfPzOw4uv2irjwcy2fSOfP1RQqAQek/6t48XMQ3nzEnsxdv9Jk1S8PDVy0myUz5dDo2ZXnsjGN7HuagUqXys0FFo1KpXJmHg//+rUaGZ2/cKtMXMkly/Y1j+k5bj8xLAFxexAD4el4eZZ32uSluGpIsiN/8tym5+VNKGgCnFC4AyknysbycgI5h1bDmtDluHJLMubecMSd0Dq/m532KcvmAIj4BmJ6nF1rG97SFey+c7wYiyZwax/A4ludp7mlJkqmFC4D29va3xrcb83QiJo9vD/dcIAJIMm/GdV2mTByWt68pnuns7HzLoCJSTpIb8/ZpS4yAn1+wwA1Fkjma/LfYbFj+PqdM58hBRaVUqRybx+9bJ41rEwEkmQPjan+5nPxfeAHwq4UNgEqlsnNeF7kQASRp8u/nJYB3LmwAJEnyrvQf+bwIIEma/F/i83GOHFRk0n/ktXle7rIeAeeLAJLM0uS/+YT2vC+nvHJQ0alUKp/I+5rXE8eKAJLMxKd+xZj849//D2qGAKil/9g/iQCSpMm/7p+KtgPgq/8ZoFy+qgi7X8UFJu4+d54bkSQH2J+dP7/+Q6wQWyhXKlcMahZKSbJHUbbAFAEkOfCT/2ZjijH51x//p3Ni0wRAXOko/Uf/pkgRcJcIIEmTf+99qFqt/s2gZiL9R3++QCcwjOsWASRp8u/15j//OqjZqFQqranPigCS5Gv50/MKOPlXKs+kv/6TQc1I+o8/qWAnUwSQZD9M/hOKN/nHX/8nDGpW4lOA9CA8XcQIuPMcEUCSG+tPvlfQyT/99V8qldoHNTNpBBxXwBMrAkjS5L+uT/+OG9TstLS0bJoejN8V8QSP7W4VASRp8n+5jw9paysPQv0pwP4FPcn1CPjR2XPd0CTZm8m/p7Wok3/89f9RM///8sb0gNwuAkiyuf3xd+cVevJP/WGc80z7f/mngGp1SnpgnhMBJGnyL6jPxbnOjP/Kfwo4ssAnvh4Bd5ztnQCSbMLJPz76P9xM/2pMmvSm9CDdVOQLYMxoEUCSL5/845LqRR7749wW5zgT/bqfAoyMb0iKAJIsvnEztSaY/J+Ic5sZfv0iYNu4P7IIIEmTf879czqnbWdm782WwZXKvxT8onghAs4SASSbzzj29YxqLfrkH+JcZkbvPa8rl8tnFf3iGNVVC7ecMceAQLJpvP2suU0x+ZeT5Jw4l5nON4ChQ4e+PT2Id4kAkjT55+yN/yvb29vfaibf2KWCk+SOZoiAm0UASZN/EX753zhkyJB3mMH7gE033bSlGZ4EdI9sDWtOEwEki+ea02aH0ekPncJP/pXKnemv/yFmbk8Ceu3wjmq45PiZBgyShfHi42aEjmHVZpj8f1yr1Spm7P57EnBn4f92lFTCYX8/Pjx5/VKDB8nc+vvrloRP7Tu+PqY1wy//OEeZqfs/An7UBBdTmDi2LXz9s1PC71YtNpiQzI2PrlwcTjlyi7DZmLZmmPijPzL5D9QaAaXS0CLvHvhyh7VXw4feMzp86ROTwgXHTq//LS0uInTPBfNJsqHGsWj1N2eH8786vT5GxbEqjlnNMj6n3j2kra1sZhYBJEmTPwYiAkqVym0uQpLkAHvX0KFDS2ZiEUCSNPljoGltbd0kPSE/cFGSJE3+zRkBN7k4SZL95A8t8iMCSJImf2SJ9vb2/yMCSJIm/2aNgCS50UVLktxIbzX5iwCSZJNN/kmSvMuMKgJIkiZ/5CoCyuU1LmaSpMlfBJAk+UreYvIvGJt0dPydCCBJmvybNAIqlcpqFzlJ8uWTf7VaHWymFAEkyebxZpO/CCBJmvzRBBFwg4ufJE3+EAEkyebwByZ/ESACSLKJjGN+HPvNgBg0ePDgd5YqlevdGCRp8kcTRkB6cVznBiHJYhp/6MWx3oyHv2LIkCHvEAEkWUivM/ljnbS0tLytXC5f5WYhSZM/mvNJwDVuGpLMvdfGMd3MhvVm6NChb08vnMvcPCSZU8vlNSZ/bBCdnZ1vKVUq57uRSDJ3b/tfEH/Imcmw4Uya9Kb0YjrdDUWSufG0OHabwNAXvC6tySPSi+rPbiySzKx/LlUq/xLHbNMW+pRyubxLeoH90U1GkpnzqfSH2s5mKvQbpVKpO73Q7nSzkWRm/EmSJOPNUBiQzwRLlcoZbjqSbLBJ8k0v+2HAqVQqO6UX4G/dhCQ54P66lCQ7mInQyD8JDPWVAEkO7Fv+SZK8ywyErITA7PSivNmNSZL95g/K5fIsMw6yyOsrlcqy9CK9341Kkn3mfaUk+VAcY00zyDaTJr0pvVj3SC/au924JLnB3lWf+C3qg5w+EXhPOUkuTi/k593MJPmaPl8uly9Kx87t/OJHIUiSpFqqVD7jqQBJvqJ3p7/2D4tjpRkDRY6BrjQGDi6/sOXwc258kk1oHPuuiWNhHBPNDGg6Wlpa3pZe/PMrlcrh6Y1wXnzZxcBAsoDeG8e4uFZ/HPPi2GcGAF5GfaXBUqmnVK1uVS6X90n9bOp/pTfQuakr4h7X6X/+qJwk95BkQ41j0Qtj0or6GJWOVekPmiPj2BXHsDiWxTHNyA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATcP/A/VYuD9l6UjwAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI0LTA5LTA0VDIzOjExOjM1KzAwOjAw9BAQcQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNC0wOS0wNFQyMzoxMTozNSswMDowMIVNqM0AAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAV3pUWHRSYXcgcHJvZmlsZSB0eXBlIGlwdGMAAHic4/IMCHFWKCjKT8vMSeVSAAMjCy5jCxMjE0uTFAMTIESANMNkAyOzVCDL2NTIxMzEHMQHy4BIoEouAOoXEXTyQjWVAAAAAElFTkSuQmCC";
296
346
 
297
347
  // src/provider.ts
298
348
  var BaseProvider = class {
299
- constructor(options) {
349
+ constructor() {
300
350
  this.id = "controller";
301
351
  this.name = "Controller";
302
- this.version = "0.4.0";
352
+ this.version = package_default.version;
303
353
  this.icon = icon;
304
354
  this.subscriptions = [];
305
355
  this.request = async (call) => {
@@ -314,8 +364,9 @@ var BaseProvider = class {
314
364
  if (this.account) {
315
365
  return [this.account.address];
316
366
  }
367
+ const silentMode = call.params && call.params.silent_mode;
317
368
  this.account = await this.probe();
318
- if (!this.account) {
369
+ if (!this.account && !silentMode) {
319
370
  this.account = await this.connect();
320
371
  }
321
372
  if (this.account) {
@@ -329,24 +380,20 @@ var BaseProvider = class {
329
380
  message: "An unexpected error occurred",
330
381
  data: "wallet_watchAsset not implemented"
331
382
  };
332
- case "wallet_addStarknetChain":
333
- throw {
334
- code: 63,
335
- message: "An unexpected error occurred",
336
- data: "wallet_addStarknetChain not implemented"
337
- };
338
- case "wallet_switchStarknetChain":
339
- throw {
340
- code: 63,
341
- message: "An unexpected error occurred",
342
- data: "wallet_switchStarknetChain not implemented"
343
- };
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
+ }
344
391
  case "wallet_requestChainId":
345
392
  if (!this.account) {
346
393
  throw {
347
394
  code: 63,
348
395
  message: "An unexpected error occurred",
349
- data: "wallet_deploymentData not implemented"
396
+ data: "Account not initialized"
350
397
  };
351
398
  }
352
399
  return await this.account.getChainId();
@@ -361,7 +408,7 @@ var BaseProvider = class {
361
408
  throw {
362
409
  code: 63,
363
410
  message: "An unexpected error occurred",
364
- data: "wallet_deploymentData not implemented"
411
+ data: "Account not initialized"
365
412
  };
366
413
  }
367
414
  let params = call.params;
@@ -417,16 +464,60 @@ var BaseProvider = class {
417
464
  this.subscriptions.splice(idx, 1);
418
465
  }
419
466
  };
420
- const { rpc } = options;
421
- 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
+ });
422
477
  }
423
478
  };
424
479
 
425
480
  // src/controller.ts
481
+ import { constants } from "starknet";
426
482
  var ControllerProvider = class extends BaseProvider {
427
483
  constructor(options) {
428
- const { rpc } = options;
429
- 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
+ }
430
521
  this.iframes = {
431
522
  keychain: new KeychainIFrame({
432
523
  ...options,
@@ -448,11 +539,10 @@ var ControllerProvider = class extends BaseProvider {
448
539
  console.error(new NotReadyToConnect().message);
449
540
  return;
450
541
  }
451
- const response = await this.keychain.probe(
452
- this.rpc.toString()
453
- );
542
+ const response = await this.keychain.probe(this.rpcUrl());
454
543
  this.account = new account_default(
455
544
  this,
545
+ this.rpcUrl(),
456
546
  response.address,
457
547
  this.keychain,
458
548
  this.options,
@@ -474,7 +564,7 @@ var ControllerProvider = class extends BaseProvider {
474
564
  openPurchaseCredits: () => this.openPurchaseCredits.bind(this),
475
565
  openExecute: () => this.openExecute.bind(this)
476
566
  },
477
- rpcUrl: this.rpc.toString(),
567
+ rpcUrl: this.rpcUrl(),
478
568
  username,
479
569
  version: this.version
480
570
  });
@@ -498,8 +588,8 @@ var ControllerProvider = class extends BaseProvider {
498
588
  this.iframes.keychain.open();
499
589
  try {
500
590
  let response = await this.keychain.connect(
501
- this.options.policies || [],
502
- this.rpc.toString()
591
+ this.options.policies || {},
592
+ this.rpcUrl()
503
593
  );
504
594
  if (response.code !== "SUCCESS" /* SUCCESS */) {
505
595
  throw new Error(response.message);
@@ -507,6 +597,7 @@ var ControllerProvider = class extends BaseProvider {
507
597
  response = response;
508
598
  this.account = new account_default(
509
599
  this,
600
+ this.rpcUrl(),
510
601
  response.address,
511
602
  this.keychain,
512
603
  this.options,
@@ -519,6 +610,23 @@ var ControllerProvider = class extends BaseProvider {
519
610
  this.iframes.keychain.close();
520
611
  }
521
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
+ }
522
630
  async disconnect() {
523
631
  if (!this.keychain) {
524
632
  console.error(new NotReadyToConnect().message);
@@ -571,6 +679,9 @@ var ControllerProvider = class extends BaseProvider {
571
679
  }
572
680
  return this.keychain.revoke(origin);
573
681
  }
682
+ rpcUrl() {
683
+ return this.chains.get(this.selectedChain).rpcUrl;
684
+ }
574
685
  username() {
575
686
  if (!this.keychain) {
576
687
  console.error(new NotReadyToConnect().message);