@cartridge/controller 0.5.9 → 0.7.0

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 (102) hide show
  1. package/.turbo/turbo-build$colon$deps.log +53 -115
  2. package/.turbo/turbo-build.log +54 -116
  3. package/dist/controller.cjs +860 -0
  4. package/dist/controller.cjs.map +1 -0
  5. package/dist/controller.d.cts +33 -0
  6. package/dist/controller.d.ts +4 -4
  7. package/dist/controller.js +254 -170
  8. package/dist/controller.js.map +1 -1
  9. package/dist/index.cjs +2200 -0
  10. package/dist/index.cjs.map +1 -0
  11. package/dist/index.d.cts +17 -0
  12. package/dist/index.d.ts +12 -6
  13. package/dist/index.js +296 -7666
  14. package/dist/index.js.map +1 -1
  15. package/dist/lookup.cjs +59 -0
  16. package/dist/lookup.cjs.map +1 -0
  17. package/dist/lookup.d.cts +4 -0
  18. package/dist/lookup.js +7 -7
  19. package/dist/lookup.js.map +1 -1
  20. package/dist/node/index.cjs +726 -0
  21. package/dist/node/index.cjs.map +1 -0
  22. package/dist/node/index.d.cts +56 -0
  23. package/dist/node/index.d.ts +56 -0
  24. package/dist/{telegram/provider.js → node/index.js} +521 -216
  25. package/dist/node/index.js.map +1 -0
  26. package/dist/policies-DD1aPjQ4.d.cts +21 -0
  27. package/dist/policies-DD1aPjQ4.d.ts +21 -0
  28. package/dist/{types-CVnDQVqD.d.ts → provider-ap1C1ypF.d.cts} +27 -10
  29. package/dist/provider-ap1C1ypF.d.ts +201 -0
  30. package/dist/session/{provider.js → index.cjs} +342 -168
  31. package/dist/session/index.cjs.map +1 -0
  32. package/dist/session/index.d.cts +38 -0
  33. package/dist/session/index.d.ts +37 -7
  34. package/dist/session/index.js +309 -161
  35. package/dist/session/index.js.map +1 -1
  36. package/package.json +49 -16
  37. package/src/controller.ts +44 -15
  38. package/src/iframe/base.ts +1 -11
  39. package/src/mutex.ts +22 -0
  40. package/src/node/account.ts +72 -0
  41. package/src/node/backend.ts +159 -0
  42. package/src/node/index.ts +4 -0
  43. package/src/node/provider.ts +178 -0
  44. package/src/node/server.ts +89 -0
  45. package/src/policies.ts +49 -0
  46. package/src/provider.ts +33 -2
  47. package/src/session/account.ts +2 -1
  48. package/src/session/provider.ts +123 -10
  49. package/src/telegram/provider.ts +3 -2
  50. package/src/types.ts +3 -6
  51. package/src/utils.ts +4 -1
  52. package/tsconfig.json +3 -3
  53. package/dist/__tests__/parseChainId.test.d.ts +0 -2
  54. package/dist/__tests__/parseChainId.test.js +0 -89
  55. package/dist/__tests__/parseChainId.test.js.map +0 -1
  56. package/dist/account.d.ts +0 -38
  57. package/dist/account.js +0 -106
  58. package/dist/account.js.map +0 -1
  59. package/dist/constants.d.ts +0 -5
  60. package/dist/constants.js +0 -10
  61. package/dist/constants.js.map +0 -1
  62. package/dist/errors.d.ts +0 -5
  63. package/dist/errors.js +0 -11
  64. package/dist/errors.js.map +0 -1
  65. package/dist/icon.d.ts +0 -3
  66. package/dist/icon.js +0 -6
  67. package/dist/icon.js.map +0 -1
  68. package/dist/iframe/base.d.ts +0 -5
  69. package/dist/iframe/base.js +0 -122
  70. package/dist/iframe/base.js.map +0 -1
  71. package/dist/iframe/index.d.ts +0 -5
  72. package/dist/iframe/index.js +0 -184
  73. package/dist/iframe/index.js.map +0 -1
  74. package/dist/iframe/keychain.d.ts +0 -5
  75. package/dist/iframe/keychain.js +0 -143
  76. package/dist/iframe/keychain.js.map +0 -1
  77. package/dist/iframe/profile.d.ts +0 -5
  78. package/dist/iframe/profile.js +0 -163
  79. package/dist/iframe/profile.js.map +0 -1
  80. package/dist/index.d-BbTUPBeO.d.ts +0 -68
  81. package/dist/provider.d.ts +0 -22
  82. package/dist/provider.js +0 -198
  83. package/dist/provider.js.map +0 -1
  84. package/dist/session/account.d.ts +0 -37
  85. package/dist/session/account.js +0 -92
  86. package/dist/session/account.js.map +0 -1
  87. package/dist/session/backend.d.ts +0 -60
  88. package/dist/session/backend.js +0 -39
  89. package/dist/session/backend.js.map +0 -1
  90. package/dist/session/provider.d.ts +0 -30
  91. package/dist/session/provider.js.map +0 -1
  92. package/dist/telegram/backend.d.ts +0 -33
  93. package/dist/telegram/backend.js +0 -40
  94. package/dist/telegram/backend.js.map +0 -1
  95. package/dist/telegram/provider.d.ts +0 -26
  96. package/dist/telegram/provider.js.map +0 -1
  97. package/dist/types.d.ts +0 -5
  98. package/dist/types.js +0 -13
  99. package/dist/types.js.map +0 -1
  100. package/dist/utils.d.ts +0 -18
  101. package/dist/utils.js +0 -139
  102. package/dist/utils.js.map +0 -1
@@ -1,30 +1,11 @@
1
- // src/telegram/provider.ts
2
- import {
3
- cloudStorage,
4
- miniApp,
5
- openLink,
6
- retrieveLaunchParams
7
- } from "@telegram-apps/sdk";
8
- import { ec, stark } from "starknet";
1
+ import { stark, ec, typedData, TypedDataRevision, hash, WalletAccount, addAddressPadding, CallData } from 'starknet';
2
+ import { CartridgeSessionAccount } from '@cartridge/account-wasm/session';
3
+ import { Permission } from '@starknet-io/types-js';
4
+ import * as fs from 'fs/promises';
5
+ import * as path from 'path';
6
+ import * as http from 'http';
9
7
 
10
- // src/constants.ts
11
- var KEYCHAIN_URL = "https://x.cartridge.gg";
12
-
13
- // src/session/account.ts
14
- import { CartridgeSessionAccount } from "@cartridge/account-wasm/session";
15
- import { WalletAccount } from "starknet";
16
-
17
- // src/utils.ts
18
- import {
19
- addAddressPadding,
20
- CallData,
21
- constants,
22
- getChecksumAddress,
23
- hash,
24
- shortString,
25
- typedData,
26
- TypedDataRevision
27
- } from "starknet";
8
+ // src/node/provider.ts
28
9
  function normalizeCalls(calls) {
29
10
  return toArray(calls).map((call) => {
30
11
  return {
@@ -39,7 +20,8 @@ function toWasmPolicies(policies) {
39
20
  ...Object.entries(policies.contracts ?? {}).flatMap(
40
21
  ([target, { methods }]) => toArray(methods).map((m) => ({
41
22
  target,
42
- method: m.entrypoint
23
+ method: m.entrypoint,
24
+ authorized: m.authorized
43
25
  }))
44
26
  ),
45
27
  ...(policies.messages ?? []).map((p) => {
@@ -55,7 +37,8 @@ function toWasmPolicies(policies) {
55
37
  TypedDataRevision.ACTIVE
56
38
  );
57
39
  return {
58
- scope_hash: hash.computePoseidonHash(domainHash, typeHash)
40
+ scope_hash: hash.computePoseidonHash(domainHash, typeHash),
41
+ authorized: p.authorized
59
42
  };
60
43
  })
61
44
  ];
@@ -64,8 +47,27 @@ function toArray(val) {
64
47
  return Array.isArray(val) ? val : [val];
65
48
  }
66
49
 
67
- // src/session/account.ts
50
+ // src/errors.ts
51
+ var NotReadyToConnect = class _NotReadyToConnect extends Error {
52
+ constructor() {
53
+ super("Not ready to connect");
54
+ Object.setPrototypeOf(this, _NotReadyToConnect.prototype);
55
+ }
56
+ };
57
+
58
+ // src/types.ts
59
+ var ResponseCodes = /* @__PURE__ */ ((ResponseCodes2) => {
60
+ ResponseCodes2["SUCCESS"] = "SUCCESS";
61
+ ResponseCodes2["NOT_CONNECTED"] = "NOT_CONNECTED";
62
+ ResponseCodes2["ERROR"] = "ERROR";
63
+ ResponseCodes2["CANCELED"] = "CANCELED";
64
+ ResponseCodes2["USER_INTERACTION_REQUIRED"] = "USER_INTERACTION_REQUIRED";
65
+ return ResponseCodes2;
66
+ })(ResponseCodes || {});
67
+
68
+ // src/node/account.ts
68
69
  var SessionAccount = class extends WalletAccount {
70
+ controller;
69
71
  constructor(provider, {
70
72
  rpcUrl,
71
73
  privateKey,
@@ -76,7 +78,8 @@ var SessionAccount = class extends WalletAccount {
76
78
  policies
77
79
  }) {
78
80
  super({ nodeUrl: rpcUrl }, provider);
79
- this.controller = CartridgeSessionAccount.new_as_registered(
81
+ this.address = address;
82
+ this.controller = CartridgeSessionAccount.newAsRegistered(
80
83
  rpcUrl,
81
84
  privateKey,
82
85
  address,
@@ -96,30 +99,34 @@ var SessionAccount = class extends WalletAccount {
96
99
  * - entrypoint - the entrypoint of the contract
97
100
  * - calldata - (defaults to []) the calldata
98
101
  * - signature - (defaults to []) the signature
99
- * @param abis (optional) the abi of the contract for better displaying
100
102
  *
101
103
  * @returns response from addTransaction
102
104
  */
103
105
  async execute(calls) {
104
- return this.controller.execute(normalizeCalls(calls));
106
+ try {
107
+ const res = await this.controller.executeFromOutside(
108
+ normalizeCalls(calls)
109
+ );
110
+ return res;
111
+ } catch (e) {
112
+ return this.controller.execute(normalizeCalls(calls));
113
+ }
105
114
  }
106
115
  };
107
116
 
108
- // src/provider.ts
109
- import {
110
- Permission
111
- } from "@starknet-io/types-js";
117
+ // src/constants.ts
118
+ var KEYCHAIN_URL = "https://x.cartridge.gg";
112
119
 
113
120
  // package.json
114
121
  var package_default = {
115
122
  name: "@cartridge/controller",
116
- version: "0.5.9",
123
+ version: "0.7.0",
117
124
  description: "Cartridge Controller",
118
125
  module: "dist/index.js",
119
126
  types: "dist/index.d.ts",
120
127
  type: "module",
121
128
  scripts: {
122
- "build:deps": "tsup --dts-resolve",
129
+ "build:deps": "tsup",
123
130
  build: "pnpm build:deps",
124
131
  format: 'prettier --write "src/**/*.ts"',
125
132
  "format:check": 'prettier --check "src/**/*.ts"',
@@ -127,167 +134,240 @@ var package_default = {
127
134
  version: "pnpm pkg get version"
128
135
  },
129
136
  exports: {
130
- ".": "./dist/index.js",
131
- "./session": "./dist/session/index.js",
132
- "./provider": "./dist/provider/index.js",
133
- "./types": "./dist/types/index.js"
137
+ ".": {
138
+ types: "./dist/index.d.ts",
139
+ import: "./dist/index.js",
140
+ require: "./dist/index.cjs"
141
+ },
142
+ "./session": {
143
+ types: "./dist/session/index.d.ts",
144
+ import: "./dist/session/index.js",
145
+ require: "./dist/session/index.cjs"
146
+ },
147
+ "./session/node": {
148
+ types: "./dist/node/index.d.ts",
149
+ import: "./dist/node/index.js",
150
+ require: "./dist/node/index.cjs"
151
+ },
152
+ "./provider": {
153
+ types: "./dist/provider/index.d.ts",
154
+ import: "./dist/provider/index.js"
155
+ },
156
+ "./types": {
157
+ types: "./dist/types/index.d.ts",
158
+ import: "./dist/types/index.js"
159
+ }
134
160
  },
135
161
  tsup: {
136
162
  entry: [
137
- "src/**"
163
+ "src/index.ts",
164
+ "src/controller.ts",
165
+ "src/lookup.ts",
166
+ "src/session/index.ts",
167
+ "src/node/index.ts"
138
168
  ],
139
169
  format: [
140
- "esm"
170
+ "esm",
171
+ "cjs"
141
172
  ],
142
173
  splitting: false,
143
174
  sourcemap: true,
144
- clean: true
175
+ clean: true,
176
+ dts: true,
177
+ treeshake: {
178
+ preset: "recommended"
179
+ },
180
+ exports: "named"
181
+ },
182
+ peerDependencies: {
183
+ starknet: "catalog:",
184
+ open: "^10.1.0"
145
185
  },
146
186
  dependencies: {
147
187
  "@cartridge/account-wasm": "workspace:*",
148
- "@cartridge/penpal": "^6.2.3",
149
- "@starknet-io/types-js": "^0.7.7",
188
+ "@cartridge/penpal": "catalog:",
189
+ "@starknet-io/types-js": "catalog:",
150
190
  "@telegram-apps/sdk": "^2.4.0",
151
- base64url: "^3.0.1",
191
+ base64url: "catalog:",
152
192
  "cbor-x": "^1.5.0",
153
- "fast-deep-equal": "^3.1.3",
154
- "query-string": "^7.1.1",
155
- starknet: "^6.11.0"
193
+ "fast-deep-equal": "catalog:"
156
194
  },
157
195
  devDependencies: {
158
196
  "@cartridge/tsconfig": "workspace:*",
159
197
  "@types/jest": "^29.5.14",
160
- "@types/node": "^20.6.0",
198
+ "@types/node": "catalog:",
161
199
  jest: "^29.7.0",
200
+ prettier: "catalog:",
162
201
  "ts-jest": "^29.2.5",
163
- typescript: "^5.4.5"
202
+ tsup: "catalog:",
203
+ typescript: "catalog:"
164
204
  }
165
205
  };
166
206
 
167
207
  // src/icon.ts
168
208
  var icon = "data:image/png;base64,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";
169
209
 
210
+ // src/mutex.ts
211
+ function releaseStub() {
212
+ }
213
+ var Mutex = class {
214
+ m_lastPromise = Promise.resolve();
215
+ /**
216
+ * Acquire lock
217
+ * @param [bypass=false] option to skip lock acquisition
218
+ */
219
+ async obtain(bypass = false) {
220
+ let release = releaseStub;
221
+ if (bypass) return release;
222
+ const lastPromise = this.m_lastPromise;
223
+ this.m_lastPromise = new Promise((resolve) => release = resolve);
224
+ await lastPromise;
225
+ return release;
226
+ }
227
+ };
228
+
170
229
  // src/provider.ts
230
+ var mutex = new Mutex();
171
231
  var BaseProvider = class {
172
- constructor() {
173
- this.id = "controller";
174
- this.name = "Controller";
175
- this.version = package_default.version;
176
- this.icon = icon;
177
- this.subscriptions = [];
178
- this.request = async (call) => {
179
- switch (call.type) {
180
- case "wallet_getPermissions":
181
- await this.probe();
182
- if (this.account) {
183
- return [Permission.ACCOUNTS];
184
- }
185
- return [];
186
- case "wallet_requestAccounts": {
187
- if (this.account) {
188
- return [this.account.address];
189
- }
190
- const silentMode = call.params && call.params.silent_mode;
191
- this.account = await this.probe();
192
- if (!this.account && !silentMode) {
193
- this.account = await this.connect();
194
- }
195
- if (this.account) {
196
- return [this.account.address];
197
- }
198
- return [];
232
+ id = "controller";
233
+ name = "Controller";
234
+ version = package_default.version;
235
+ icon = icon;
236
+ account;
237
+ subscriptions = [];
238
+ _probePromise = null;
239
+ async safeProbe() {
240
+ if (this.account) {
241
+ return this.account;
242
+ }
243
+ if (this._probePromise) {
244
+ return this._probePromise;
245
+ }
246
+ const release = await mutex.obtain();
247
+ return await new Promise(async (resolve) => {
248
+ try {
249
+ this._probePromise = this.probe();
250
+ const result = await this._probePromise;
251
+ resolve(result);
252
+ } finally {
253
+ this._probePromise = null;
254
+ }
255
+ }).finally(() => {
256
+ release();
257
+ });
258
+ }
259
+ request = async (call) => {
260
+ switch (call.type) {
261
+ case "wallet_getPermissions":
262
+ await this.safeProbe();
263
+ if (this.account) {
264
+ return [Permission.ACCOUNTS];
199
265
  }
200
- case "wallet_watchAsset":
201
- throw {
202
- code: 63,
203
- message: "An unexpected error occurred",
204
- data: "wallet_watchAsset not implemented"
205
- };
206
- case "wallet_addStarknetChain": {
207
- let params2 = call.params;
208
- return this.addStarknetChain(params2);
266
+ return [];
267
+ case "wallet_requestAccounts": {
268
+ if (this.account) {
269
+ return [this.account.address];
209
270
  }
210
- case "wallet_switchStarknetChain": {
211
- let params2 = call.params;
212
- return this.switchStarknetChain(params2.chainId);
271
+ const silentMode = call.params && call.params.silent_mode;
272
+ this.account = await this.safeProbe();
273
+ if (!this.account && !silentMode) {
274
+ this.account = await this.connect();
213
275
  }
214
- case "wallet_requestChainId":
215
- if (!this.account) {
216
- throw {
217
- code: 63,
218
- message: "An unexpected error occurred",
219
- data: "Account not initialized"
220
- };
221
- }
222
- return await this.account.getChainId();
223
- case "wallet_deploymentData":
276
+ if (this.account) {
277
+ return [this.account.address];
278
+ }
279
+ return [];
280
+ }
281
+ case "wallet_watchAsset":
282
+ throw {
283
+ code: 63,
284
+ message: "An unexpected error occurred",
285
+ data: "wallet_watchAsset not implemented"
286
+ };
287
+ case "wallet_addStarknetChain": {
288
+ let params2 = call.params;
289
+ return this.addStarknetChain(params2);
290
+ }
291
+ case "wallet_switchStarknetChain": {
292
+ let params2 = call.params;
293
+ return this.switchStarknetChain(params2.chainId);
294
+ }
295
+ case "wallet_requestChainId":
296
+ if (!this.account) {
224
297
  throw {
225
298
  code: 63,
226
299
  message: "An unexpected error occurred",
227
- data: "wallet_deploymentData not implemented"
300
+ data: "Account not initialized"
228
301
  };
229
- case "wallet_addInvokeTransaction":
230
- if (!this.account) {
231
- throw {
232
- code: 63,
233
- message: "An unexpected error occurred",
234
- data: "Account not initialized"
235
- };
236
- }
237
- let params = call.params;
238
- return await this.account.execute(
239
- params.calls.map((call2) => ({
240
- contractAddress: call2.contract_address,
241
- entrypoint: call2.entry_point,
242
- calldata: call2.calldata
243
- }))
244
- );
245
- case "wallet_addDeclareTransaction":
302
+ }
303
+ return await this.account.getChainId();
304
+ case "wallet_deploymentData":
305
+ throw {
306
+ code: 63,
307
+ message: "An unexpected error occurred",
308
+ data: "wallet_deploymentData not implemented"
309
+ };
310
+ case "wallet_addInvokeTransaction":
311
+ if (!this.account) {
246
312
  throw {
247
313
  code: 63,
248
314
  message: "An unexpected error occurred",
249
- data: "wallet_addDeclareTransaction not implemented"
315
+ data: "Account not initialized"
250
316
  };
251
- case "wallet_signTypedData": {
252
- if (!this.account) {
253
- throw {
254
- code: 63,
255
- message: "An unexpected error occurred",
256
- data: "Account not initialized"
257
- };
258
- }
259
- return await this.account.signMessage(call.params);
260
317
  }
261
- case "wallet_supportedSpecs":
262
- return [];
263
- case "wallet_supportedWalletApi":
264
- return [];
265
- default:
318
+ let params = call.params;
319
+ return await this.account.execute(
320
+ params.calls.map((call2) => ({
321
+ contractAddress: call2.contract_address,
322
+ entrypoint: call2.entry_point,
323
+ calldata: call2.calldata
324
+ }))
325
+ );
326
+ case "wallet_addDeclareTransaction":
327
+ throw {
328
+ code: 63,
329
+ message: "An unexpected error occurred",
330
+ data: "wallet_addDeclareTransaction not implemented"
331
+ };
332
+ case "wallet_signTypedData": {
333
+ if (!this.account) {
266
334
  throw {
267
335
  code: 63,
268
336
  message: "An unexpected error occurred",
269
- data: `Unknown RPC call type: ${call.type}`
337
+ data: "Account not initialized"
270
338
  };
339
+ }
340
+ return await this.account.signMessage(call.params);
271
341
  }
272
- };
273
- this.on = (event, handler) => {
274
- if (event !== "accountsChanged" && event !== "networkChanged") {
275
- throw new Error(`Unknown event: ${event}`);
276
- }
277
- this.subscriptions.push({ type: event, handler });
278
- };
279
- this.off = (event, handler) => {
280
- if (event !== "accountsChanged" && event !== "networkChanged") {
281
- throw new Error(`Unknown event: ${event}`);
282
- }
283
- const idx = this.subscriptions.findIndex(
284
- (sub) => sub.type === event && sub.handler === handler
285
- );
286
- if (idx >= 0) {
287
- this.subscriptions.splice(idx, 1);
288
- }
289
- };
290
- }
342
+ case "wallet_supportedSpecs":
343
+ return [];
344
+ case "wallet_supportedWalletApi":
345
+ return [];
346
+ default:
347
+ throw {
348
+ code: 63,
349
+ message: "An unexpected error occurred",
350
+ data: `Unknown RPC call type: ${call.type}`
351
+ };
352
+ }
353
+ };
354
+ on = (event, handler) => {
355
+ if (event !== "accountsChanged" && event !== "networkChanged") {
356
+ throw new Error(`Unknown event: ${event}`);
357
+ }
358
+ this.subscriptions.push({ type: event, handler });
359
+ };
360
+ off = (event, handler) => {
361
+ if (event !== "accountsChanged" && event !== "networkChanged") {
362
+ throw new Error(`Unknown event: ${event}`);
363
+ }
364
+ const idx = this.subscriptions.findIndex(
365
+ (sub) => sub.type === event && sub.handler === handler
366
+ );
367
+ if (idx >= 0) {
368
+ this.subscriptions.splice(idx, 1);
369
+ }
370
+ };
291
371
  emitNetworkChanged(chainId) {
292
372
  this.subscriptions.filter((sub) => sub.type === "networkChanged").forEach((sub) => {
293
373
  sub.handler(chainId);
@@ -299,49 +379,311 @@ var BaseProvider = class {
299
379
  });
300
380
  }
301
381
  };
382
+ var CallbackServer = class {
383
+ server;
384
+ resolveCallback;
385
+ rejectCallback;
386
+ timeoutId;
387
+ constructor() {
388
+ this.server = http.createServer(this.handleRequest.bind(this));
389
+ this.server.on("error", (error) => {
390
+ console.error("Server error:", error);
391
+ if (this.rejectCallback) {
392
+ this.rejectCallback(error);
393
+ }
394
+ });
395
+ }
396
+ cleanup() {
397
+ if (this.timeoutId) {
398
+ clearTimeout(this.timeoutId);
399
+ }
400
+ this.server.close();
401
+ }
402
+ handleRequest(req, res) {
403
+ if (!req.url?.startsWith("/callback")) {
404
+ res.writeHead(404);
405
+ res.end();
406
+ return;
407
+ }
408
+ const params = new URLSearchParams(req.url.split("?")[1]);
409
+ const session = params.get("startapp");
410
+ if (!session) {
411
+ console.warn("Received callback without session data");
412
+ res.writeHead(400);
413
+ res.end("Missing session data");
414
+ return;
415
+ }
416
+ if (this.resolveCallback) {
417
+ this.resolveCallback(session);
418
+ }
419
+ res.writeHead(200, { "Content-Type": "text/html" });
420
+ res.end(
421
+ "<html><body><script>window.close();</script>Session registered successfully. You can close this window.</body></html>"
422
+ );
423
+ this.cleanup();
424
+ }
425
+ async listen() {
426
+ return new Promise((resolve, reject) => {
427
+ this.server.listen(0, "localhost", () => {
428
+ const address = this.server.address();
429
+ const url = `http://localhost:${address.port}/callback`;
430
+ resolve(url);
431
+ });
432
+ this.server.on("error", reject);
433
+ });
434
+ }
435
+ async waitForCallback() {
436
+ return new Promise((resolve, reject) => {
437
+ this.resolveCallback = resolve;
438
+ this.rejectCallback = reject;
439
+ this.timeoutId = setTimeout(
440
+ () => {
441
+ console.warn("Callback timeout reached");
442
+ reject(new Error("Callback timeout after 5 minutes"));
443
+ this.cleanup();
444
+ },
445
+ 5 * 60 * 1e3
446
+ );
447
+ });
448
+ }
449
+ };
450
+
451
+ // src/node/backend.ts
452
+ var NodeBackend = class {
453
+ basePath;
454
+ sessionFile;
455
+ data = {};
456
+ callbackServer;
457
+ constructor(basePath) {
458
+ if (!basePath) {
459
+ throw new Error("basePath is required for NodeBackend");
460
+ }
461
+ this.basePath = basePath;
462
+ this.sessionFile = path.join(this.basePath, "session.json");
463
+ }
464
+ async ensureDirectoryExists() {
465
+ try {
466
+ await fs.access(this.basePath);
467
+ } catch {
468
+ try {
469
+ await fs.mkdir(this.basePath, { recursive: true });
470
+ } catch (error) {
471
+ throw new Error(
472
+ `Failed to create directory ${this.basePath}: ${error.message}`
473
+ );
474
+ }
475
+ }
476
+ }
477
+ async loadData() {
478
+ try {
479
+ const content = await fs.readFile(this.sessionFile, "utf-8");
480
+ const parsed = JSON.parse(content);
481
+ if (typeof parsed !== "object" || parsed === null) {
482
+ throw new Error("Invalid session data format");
483
+ }
484
+ this.data = parsed;
485
+ } catch (error) {
486
+ if (error instanceof Error) {
487
+ if (error.code !== "ENOENT") {
488
+ throw new Error(`Failed to load session data: ${error.message}`);
489
+ }
490
+ }
491
+ this.data = {};
492
+ }
493
+ }
494
+ async saveData() {
495
+ try {
496
+ await this.ensureDirectoryExists();
497
+ await fs.writeFile(
498
+ this.sessionFile,
499
+ JSON.stringify(this.data, null, 2),
500
+ "utf-8"
501
+ );
502
+ } catch (error) {
503
+ if (error instanceof Error) {
504
+ throw new Error(`Failed to save session data: ${error.message}`);
505
+ }
506
+ throw error;
507
+ }
508
+ }
509
+ async get(key) {
510
+ if (!key) {
511
+ throw new Error("Key is required");
512
+ }
513
+ await this.loadData();
514
+ return this.data[key] ? JSON.stringify(this.data[key]) : null;
515
+ }
516
+ async set(key, value) {
517
+ if (!key) {
518
+ throw new Error("Key is required");
519
+ }
520
+ if (!value) {
521
+ throw new Error("Value is required");
522
+ }
523
+ await this.loadData();
524
+ try {
525
+ this.data[key] = JSON.parse(value);
526
+ await this.saveData();
527
+ } catch (error) {
528
+ if (error instanceof Error) {
529
+ throw new Error(`Failed to set ${key}: ${error.message}`);
530
+ }
531
+ throw error;
532
+ }
533
+ }
534
+ async delete(key) {
535
+ if (!key) {
536
+ throw new Error("Key is required");
537
+ }
538
+ await this.loadData();
539
+ delete this.data[key];
540
+ await this.saveData();
541
+ }
542
+ async getRedirectUri() {
543
+ try {
544
+ this.callbackServer = new CallbackServer();
545
+ return await this.callbackServer.listen();
546
+ } catch (error) {
547
+ if (error instanceof Error) {
548
+ throw new Error(`Failed to start callback server: ${error.message}`);
549
+ }
550
+ throw error;
551
+ }
552
+ }
553
+ async waitForCallback() {
554
+ if (!this.callbackServer) {
555
+ throw new Error("Callback server not initialized");
556
+ }
557
+ return await this.callbackServer.waitForCallback();
558
+ }
559
+ openLink(url) {
560
+ if (!url) {
561
+ throw new Error("URL is required");
562
+ }
563
+ console.log(`
564
+ Open url to authorize session: ${url}`);
565
+ }
566
+ };
302
567
 
303
- // src/telegram/provider.ts
304
- var TelegramProvider = class extends BaseProvider {
568
+ // src/node/provider.ts
569
+ var SessionProvider = class extends BaseProvider {
570
+ id = "controller_session";
571
+ name = "Controller Session";
572
+ _chainId;
573
+ _rpcUrl;
574
+ _username;
575
+ _policies;
576
+ _keychainUrl;
577
+ _backend;
305
578
  constructor({
306
579
  rpc,
307
580
  chainId,
308
581
  policies,
309
- tmaUrl
582
+ basePath,
583
+ keychainUrl
310
584
  }) {
311
585
  super();
586
+ this._policies = {
587
+ verified: false,
588
+ contracts: policies.contracts ? Object.fromEntries(
589
+ Object.entries(policies.contracts).map(([address, contract]) => [
590
+ address,
591
+ {
592
+ ...contract,
593
+ methods: contract.methods.map((method) => ({
594
+ ...method,
595
+ authorized: true
596
+ }))
597
+ }
598
+ ])
599
+ ) : undefined,
600
+ messages: policies.messages?.map((message) => ({
601
+ ...message,
602
+ authorized: true
603
+ }))
604
+ };
312
605
  this._rpcUrl = rpc;
313
- this._tmaUrl = tmaUrl;
314
606
  this._chainId = chainId;
315
- this._policies = policies;
316
- if (typeof window !== "undefined") {
317
- window.starknet_controller = this;
607
+ this._keychainUrl = keychainUrl || KEYCHAIN_URL;
608
+ this._backend = new NodeBackend(basePath);
609
+ }
610
+ async username() {
611
+ const sessionStr = await this._backend.get("session");
612
+ if (sessionStr) {
613
+ const session = JSON.parse(sessionStr);
614
+ return session.username;
318
615
  }
616
+ return undefined;
319
617
  }
320
618
  async probe() {
321
- await this.tryRetrieveFromQueryOrStorage();
322
- return;
619
+ if (this.account) {
620
+ return this.account;
621
+ }
622
+ const [sessionStr, signerStr] = await Promise.all([
623
+ this._backend.get("session"),
624
+ this._backend.get("signer")
625
+ ]);
626
+ if (!sessionStr || !signerStr) {
627
+ return undefined;
628
+ }
629
+ const session = JSON.parse(sessionStr);
630
+ const signer = JSON.parse(signerStr);
631
+ const expirationTime = parseInt(session.expiresAt) * 1e3;
632
+ if (Date.now() >= expirationTime) {
633
+ await this.disconnect();
634
+ return undefined;
635
+ }
636
+ this._username = session.username;
637
+ this.account = new SessionAccount(this, {
638
+ rpcUrl: this._rpcUrl,
639
+ privateKey: signer.privKey,
640
+ address: session.address,
641
+ ownerGuid: session.ownerGuid,
642
+ chainId: this._chainId,
643
+ expiresAt: parseInt(session.expiresAt),
644
+ policies: toWasmPolicies(this._policies)
645
+ });
646
+ return this.account;
323
647
  }
324
648
  async connect() {
325
- await this.tryRetrieveFromQueryOrStorage();
326
649
  if (this.account) {
327
- return;
650
+ return this.account;
651
+ }
652
+ const account = await this.probe();
653
+ if (account) {
654
+ return account;
328
655
  }
329
656
  const pk = stark.randomAddress();
330
657
  const publicKey = ec.starkCurve.getStarkKey(pk);
331
- cloudStorage.setItem(
332
- "sessionSigner",
658
+ await this._backend.set(
659
+ "signer",
333
660
  JSON.stringify({
334
661
  privKey: pk,
335
662
  pubKey: publicKey
336
663
  })
337
664
  );
338
- const url = `${KEYCHAIN_URL}/session?public_key=${publicKey}&redirect_uri=${this._tmaUrl}&redirect_query_name=startapp&policies=${JSON.stringify(
339
- this._policies
340
- )}&rpc_url=${this._rpcUrl}`;
341
- localStorage.setItem("lastUsedConnector", this.id);
342
- openLink(url);
343
- miniApp.close();
344
- return;
665
+ const redirectUri = await this._backend.getRedirectUri();
666
+ const url = `${this._keychainUrl}/session?public_key=${encodeURIComponent(publicKey)}&redirect_uri=${encodeURIComponent(
667
+ redirectUri
668
+ )}&redirect_query_name=startapp&policies=${encodeURIComponent(
669
+ JSON.stringify(this._policies)
670
+ )}&rpc_url=${encodeURIComponent(this._rpcUrl)}`;
671
+ this._backend.openLink(url);
672
+ const sessionData = await this._backend.waitForCallback();
673
+ if (sessionData) {
674
+ const sessionRegistration = JSON.parse(atob(sessionData));
675
+ sessionRegistration.address = sessionRegistration.address.toLowerCase();
676
+ sessionRegistration.ownerGuid = sessionRegistration.ownerGuid.toLowerCase();
677
+ await this._backend.set("session", JSON.stringify(sessionRegistration));
678
+ return this.probe();
679
+ }
680
+ return undefined;
681
+ }
682
+ async disconnect() {
683
+ await this._backend.delete("signer");
684
+ await this._backend.delete("session");
685
+ this.account = undefined;
686
+ this._username = undefined;
345
687
  }
346
688
  switchStarknetChain(_chainId) {
347
689
  throw new Error("switchStarknetChain not implemented");
@@ -349,45 +691,8 @@ var TelegramProvider = class extends BaseProvider {
349
691
  addStarknetChain(_chain) {
350
692
  throw new Error("addStarknetChain not implemented");
351
693
  }
352
- disconnect() {
353
- cloudStorage.deleteItem("sessionSigner");
354
- cloudStorage.deleteItem("session");
355
- this.account = void 0;
356
- this._username = void 0;
357
- return Promise.resolve();
358
- }
359
- async tryRetrieveFromQueryOrStorage() {
360
- const signer = JSON.parse(await cloudStorage.getItem("sessionSigner"));
361
- let sessionRegistration = null;
362
- const launchParams = retrieveLaunchParams();
363
- const session = launchParams.startParam;
364
- if (session) {
365
- sessionRegistration = JSON.parse(atob(session));
366
- cloudStorage.setItem("session", JSON.stringify(sessionRegistration));
367
- }
368
- if (!sessionRegistration) {
369
- const session2 = await cloudStorage.getItem("session");
370
- if (session2) {
371
- sessionRegistration = JSON.parse(session2);
372
- }
373
- }
374
- if (!sessionRegistration) {
375
- return;
376
- }
377
- this._username = sessionRegistration.username;
378
- this.account = new SessionAccount(this, {
379
- rpcUrl: this._rpcUrl,
380
- privateKey: signer.privKey,
381
- address: sessionRegistration.address,
382
- ownerGuid: sessionRegistration.ownerGuid,
383
- chainId: this._chainId,
384
- expiresAt: parseInt(sessionRegistration.expiresAt),
385
- policies: toWasmPolicies(this._policies)
386
- });
387
- return this.account;
388
- }
389
694
  };
390
- export {
391
- TelegramProvider as default
392
- };
393
- //# sourceMappingURL=provider.js.map
695
+
696
+ export { NotReadyToConnect, ResponseCodes, SessionProvider as default };
697
+ //# sourceMappingURL=index.js.map
698
+ //# sourceMappingURL=index.js.map