@naculus/connect-appkit-core 0.13.0 → 0.15.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.
package/dist/index.cjs CHANGED
@@ -36,6 +36,7 @@ __export(src_exports, {
36
36
  chainNumber: () => chainNumber,
37
37
  chainsForNamespace: () => chainsForNamespace,
38
38
  channelsUpdate: () => channelsUpdate,
39
+ checkSessionKeyRailGrant: () => checkSessionKeyRailGrant,
39
40
  clearOneInAppNotification: () => clearOneInAppNotification,
40
41
  compareCostsKey: () => compareCostsKey,
41
42
  createDecimalsCache: () => createDecimalsCache,
@@ -769,6 +770,22 @@ function resetSharedSessionKeyManager() {
769
770
  sharedFingerprint = null;
770
771
  }
771
772
 
773
+ // src/session-key-rail.ts
774
+ var knownRails = /* @__PURE__ */ new Set([
775
+ "transfer",
776
+ "x402-exact",
777
+ "mpp-charge"
778
+ ]);
779
+ function checkSessionKeyRailGrant(scope, rail) {
780
+ const rails = scope?.rails;
781
+ if (!Array.isArray(rails) || rails.length === 0 || new Set(rails).size !== rails.length || !Array.from(rails).every(
782
+ (candidate) => typeof candidate === "string" && knownRails.has(candidate)
783
+ ) || !rails.includes(rail)) {
784
+ return { status: "needs-regrant", missingRail: rail };
785
+ }
786
+ return { status: "ok", rail };
787
+ }
788
+
772
789
  // src/user-op-receipt.ts
773
790
  var InvalidUserOperationReceiptError = class extends Error {
774
791
  constructor(message) {
@@ -993,8 +1010,21 @@ function createDelegationFrameworkAdapter(options) {
993
1010
  execution,
994
1011
  unsigned
995
1012
  };
1013
+ const hex = (value2) => `0x${value2.toString(16)}`;
996
1014
  return {
997
1015
  digest: codec.signingHash(unsigned),
1016
+ // The same redemption as `unsigned`, as a request for the digest check.
1017
+ request: {
1018
+ type: "eip1559",
1019
+ chainId: unsigned.chainId,
1020
+ nonce: hex(unsigned.nonce),
1021
+ to: unsigned.to,
1022
+ value: hex(unsigned.value),
1023
+ data: unsigned.data,
1024
+ gas: hex(unsigned.gas),
1025
+ maxFeePerGas: hex(unsigned.maxFeePerGas),
1026
+ maxPriorityFeePerGas: hex(unsigned.maxPriorityFeePerGas)
1027
+ },
998
1028
  transaction,
999
1029
  payload
1000
1030
  };
@@ -1011,6 +1041,7 @@ function createDelegationFrameworkAdapter(options) {
1011
1041
 
1012
1042
  // src/delegation-policy.ts
1013
1043
  var import_connect_core16 = require("@naculus/connect-core");
1044
+ var import_signing = require("@naculus/connect-core/signing");
1014
1045
  function delegatesToStatelessDeleGator(delegation) {
1015
1046
  return delegation.delegated === true && delegation.delegate?.toLowerCase() === import_connect_core16.DELEGATION_FRAMEWORK.eip7702StatelessDeleGator.toLowerCase();
1016
1047
  }
@@ -1286,16 +1317,39 @@ function createDelegationPolicyFlow(deps) {
1286
1317
  reason
1287
1318
  };
1288
1319
  };
1289
- const signVerified = (policyId, digest, tx) => manager.signWithVerifiedOffchainAuthorization(
1290
- policyId,
1291
- (authoritativePolicy) => buildDelegationPolicyMessage(authoritativePolicy, origin),
1292
- deps.verifySignature,
1293
- digest,
1294
- tx
1295
- );
1320
+ const signVerified = (policyId, prepared) => {
1321
+ const { request } = prepared;
1322
+ const computed = `0x${Array.from(
1323
+ (0, import_signing.transactionSigningHash)(request),
1324
+ (byte) => byte.toString(16).padStart(2, "0")
1325
+ ).join("")}`;
1326
+ if (computed !== prepared.digest.toLowerCase()) {
1327
+ throw new import_connect_core16.WalletError(
1328
+ "invalid_input",
1329
+ `The prepared digest ${prepared.digest} does not match the signing hash ${computed} of the prepared transaction request.`
1330
+ );
1331
+ }
1332
+ if (!sameExecutionIntent(prepared.transaction, {
1333
+ to: request.to,
1334
+ value: request.value,
1335
+ data: request.data,
1336
+ chainId: request.chainId
1337
+ })) {
1338
+ throw new import_connect_core16.WalletError(
1339
+ "invalid_input",
1340
+ "The prepared transaction request differs from the prepared transaction checked by the policy."
1341
+ );
1342
+ }
1343
+ return manager.signTransactionWithVerifiedOffchainAuthorization(
1344
+ policyId,
1345
+ (authoritativePolicy) => buildDelegationPolicyMessage(authoritativePolicy, origin),
1346
+ deps.verifySignature,
1347
+ request
1348
+ );
1349
+ };
1296
1350
  const signRedemption = (policyId, prepared) => {
1297
1351
  const payload = prepared.payload;
1298
- if (!payload?.outerTx || !payload.execution) {
1352
+ if (!payload?.outerTx || !payload.execution || !payload.unsigned) {
1299
1353
  throw new import_connect_core16.WalletError(
1300
1354
  "invalid_input",
1301
1355
  "The EIP-7702 adapter did not return a redemption to sign."
@@ -1319,15 +1373,33 @@ function createDelegationPolicyFlow(deps) {
1319
1373
  "The EIP-7702 adapter's execution differs from the requested transaction."
1320
1374
  );
1321
1375
  }
1322
- return manager.signDelegationRedemption(
1376
+ const { unsigned } = payload;
1377
+ const hex = (value) => `0x${value.toString(16)}`;
1378
+ const tx = {
1379
+ type: "eip1559",
1380
+ chainId: unsigned.chainId,
1381
+ nonce: hex(unsigned.nonce),
1382
+ to: unsigned.to,
1383
+ value: hex(unsigned.value),
1384
+ data: unsigned.data,
1385
+ gas: hex(unsigned.gas),
1386
+ maxFeePerGas: hex(unsigned.maxFeePerGas),
1387
+ maxPriorityFeePerGas: hex(unsigned.maxPriorityFeePerGas)
1388
+ };
1389
+ return manager.signTransactionDelegationRedemption(
1323
1390
  policyId,
1324
- prepared.digest,
1325
- payload.outerTx,
1391
+ tx,
1392
+ { gas: payload.outerTx.gas },
1326
1393
  payload.execution
1327
1394
  );
1328
1395
  };
1329
- const signPolicyDigest = async (policyId, digest, tx) => {
1330
- const preview = await previewPolicyExecution(policyId, tx, 1, "any");
1396
+ const signPolicyDigest = async (policyId, prepared) => {
1397
+ const preview = await previewPolicyExecution(
1398
+ policyId,
1399
+ prepared.transaction,
1400
+ 1,
1401
+ "any"
1402
+ );
1331
1403
  if (preview.policy?.scope.mode === "eip7702") {
1332
1404
  throw new import_connect_core16.WalletError(
1333
1405
  "method_not_allowed",
@@ -1337,7 +1409,7 @@ function createDelegationPolicyFlow(deps) {
1337
1409
  if (!preview.ready) {
1338
1410
  throw new import_connect_core16.WalletError("method_not_allowed", preview.reason);
1339
1411
  }
1340
- return signVerified(policyId, digest, tx);
1412
+ return signVerified(policyId, prepared);
1341
1413
  };
1342
1414
  const executePolicy = async (policyId, tx) => {
1343
1415
  const adapter = deps.adapter;
@@ -1379,7 +1451,7 @@ function createDelegationPolicyFlow(deps) {
1379
1451
  currentCheck.reason || "The on-chain policy authorization is not ready."
1380
1452
  );
1381
1453
  }
1382
- const signature = preview.policy.scope.mode === "eip7702" ? await signRedemption(policyId, prepared) : await signVerified(policyId, prepared.digest, prepared.transaction);
1454
+ const signature = preview.policy.scope.mode === "eip7702" ? await signRedemption(policyId, prepared) : await signVerified(policyId, prepared);
1383
1455
  const submission = await adapter.broadcast({
1384
1456
  policy: preview.policy,
1385
1457
  prepared,
@@ -1934,6 +2006,7 @@ function siwxResultToSession(result, now = /* @__PURE__ */ new Date()) {
1934
2006
  chainNumber,
1935
2007
  chainsForNamespace,
1936
2008
  channelsUpdate,
2009
+ checkSessionKeyRailGrant,
1937
2010
  clearOneInAppNotification,
1938
2011
  compareCostsKey,
1939
2012
  createDecimalsCache,