@yeying-community/web3-bs 1.0.14 → 1.0.15

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.
@@ -870,6 +870,73 @@
870
870
  function normalizeUcanExpiry(exp, fallbackMs) {
871
871
  return normalizeExpiry(exp, fallbackMs);
872
872
  }
873
+ function normalizeEthAccount(account) {
874
+ return String(account || '').trim().toLowerCase();
875
+ }
876
+ function parseUcanAccountFromIssuer(issuer) {
877
+ const normalized = String(issuer || '').trim().toLowerCase();
878
+ const prefix = 'did:pkh:eth:';
879
+ if (!normalized.startsWith(prefix))
880
+ return null;
881
+ const account = normalized.slice(prefix.length);
882
+ return account || null;
883
+ }
884
+ function getUcanIssuerForAccount(account) {
885
+ return `did:pkh:eth:${normalizeEthAccount(account)}`;
886
+ }
887
+ function extractUcanStatementPayload(message) {
888
+ if (!message || typeof message !== 'string')
889
+ return null;
890
+ const marker = 'UCAN-AUTH';
891
+ const index = message.indexOf(marker);
892
+ if (index < 0)
893
+ return null;
894
+ const jsonStart = message.indexOf('{', index + marker.length);
895
+ const jsonEnd = message.lastIndexOf('}');
896
+ if (jsonStart < 0 || jsonEnd < jsonStart)
897
+ return null;
898
+ try {
899
+ const parsed = JSON.parse(message.slice(jsonStart, jsonEnd + 1));
900
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
901
+ return null;
902
+ }
903
+ return parsed;
904
+ }
905
+ catch {
906
+ return null;
907
+ }
908
+ }
909
+ function getUcanRootServiceHosts(root) {
910
+ const payload = extractUcanStatementPayload(root.siwe?.message);
911
+ const hosts = payload?.service_hosts;
912
+ if (!hosts || typeof hosts !== 'object' || Array.isArray(hosts)) {
913
+ return null;
914
+ }
915
+ return hosts;
916
+ }
917
+ function getServiceHostMismatch(root, expectedServiceHosts) {
918
+ if (!expectedServiceHosts)
919
+ return null;
920
+ const entries = Object.entries(expectedServiceHosts)
921
+ .map(([key, value]) => [key, String(value || '').trim()])
922
+ .filter(([, value]) => Boolean(value));
923
+ if (!entries.length)
924
+ return null;
925
+ const hosts = getUcanRootServiceHosts(root);
926
+ if (!hosts) {
927
+ return {
928
+ expected: entries.map(([key, value]) => `${key}:${value}`).join('|'),
929
+ actual: '',
930
+ };
931
+ }
932
+ for (const [key, expected] of entries) {
933
+ const actual = typeof hosts[key] === 'string' ? hosts[key].trim() : '';
934
+ if (actual !== expected) {
935
+ return { expected, actual };
936
+ }
937
+ }
938
+ return null;
939
+ }
873
940
  function decodeUcanPayload(token) {
874
941
  const parts = String(token || '').split('.');
875
942
  if (parts.length < 2)
@@ -1297,6 +1364,105 @@
1297
1364
  function isRootExpired(root, nowMs) {
1298
1365
  return Boolean(root.exp && nowMs > root.exp);
1299
1366
  }
1367
+ async function resolveUcanAuthorization(options = {}) {
1368
+ const root = options.root === undefined
1369
+ ? await getStoredUcanRoot(options.sessionId || DEFAULT_SESSION_ID)
1370
+ : options.root;
1371
+ const nowMs = options.nowMs ?? Date.now();
1372
+ if (!root) {
1373
+ return { status: 'unauthorized', reason: 'missing_root', root };
1374
+ }
1375
+ if (typeof root.exp !== 'number' || root.exp <= nowMs) {
1376
+ return {
1377
+ status: 'unauthorized',
1378
+ reason: 'expired',
1379
+ root,
1380
+ expiresAt: root.exp,
1381
+ };
1382
+ }
1383
+ if (typeof root.nbf === 'number' && root.nbf > nowMs) {
1384
+ return {
1385
+ status: 'unauthorized',
1386
+ reason: 'not_before',
1387
+ root,
1388
+ expiresAt: root.exp,
1389
+ };
1390
+ }
1391
+ const accountFromIssuer = parseUcanAccountFromIssuer(root.iss);
1392
+ if (!accountFromIssuer) {
1393
+ return {
1394
+ status: 'unauthorized',
1395
+ reason: 'invalid_issuer',
1396
+ root,
1397
+ expiresAt: root.exp,
1398
+ actual: root.iss,
1399
+ };
1400
+ }
1401
+ const currentAccount = normalizeEthAccount(options.currentAccount);
1402
+ if (!currentAccount && !options.recoverAccountFromRoot) {
1403
+ return {
1404
+ status: 'unauthorized',
1405
+ reason: 'missing_account',
1406
+ root,
1407
+ account: null,
1408
+ expiresAt: root.exp,
1409
+ };
1410
+ }
1411
+ const account = currentAccount || accountFromIssuer;
1412
+ const expectedIssuer = getUcanIssuerForAccount(account);
1413
+ if (root.iss !== expectedIssuer) {
1414
+ return {
1415
+ status: 'unauthorized',
1416
+ reason: 'issuer_mismatch',
1417
+ root,
1418
+ account,
1419
+ expiresAt: root.exp,
1420
+ expected: expectedIssuer,
1421
+ actual: root.iss,
1422
+ };
1423
+ }
1424
+ if (options.expectedCapabilities &&
1425
+ !capsEqual(root.cap, options.expectedCapabilities)) {
1426
+ return {
1427
+ status: 'unauthorized',
1428
+ reason: 'capability_mismatch',
1429
+ root,
1430
+ account,
1431
+ expiresAt: root.exp,
1432
+ };
1433
+ }
1434
+ const expectedAudience = String(options.expectedAudience || '').trim();
1435
+ if (expectedAudience && root.aud !== expectedAudience) {
1436
+ return {
1437
+ status: 'unauthorized',
1438
+ reason: 'audience_mismatch',
1439
+ root,
1440
+ account,
1441
+ expiresAt: root.exp,
1442
+ expected: expectedAudience,
1443
+ actual: root.aud,
1444
+ };
1445
+ }
1446
+ const serviceHostMismatch = getServiceHostMismatch(root, options.expectedServiceHosts);
1447
+ if (serviceHostMismatch) {
1448
+ return {
1449
+ status: 'unauthorized',
1450
+ reason: 'service_host_mismatch',
1451
+ root,
1452
+ account,
1453
+ expiresAt: root.exp,
1454
+ expected: serviceHostMismatch.expected,
1455
+ actual: serviceHostMismatch.actual,
1456
+ };
1457
+ }
1458
+ return {
1459
+ status: 'authorized',
1460
+ account,
1461
+ root,
1462
+ restoredAccount: !currentAccount && account === accountFromIssuer,
1463
+ expiresAt: root.exp,
1464
+ };
1465
+ }
1300
1466
  async function getOrCreateUcanRoot(options) {
1301
1467
  const provider = options.provider || (await requireProvider());
1302
1468
  const session = options.session || (await createUcanSession({ id: options.sessionId, provider }));
@@ -2592,9 +2758,11 @@
2592
2758
  exports.normalizeUcanExpiry = normalizeUcanExpiry;
2593
2759
  exports.onAccountsChanged = onAccountsChanged;
2594
2760
  exports.onChainChanged = onChainChanged;
2761
+ exports.parseUcanAccountFromIssuer = parseUcanAccountFromIssuer;
2595
2762
  exports.refreshAccessToken = refreshAccessToken;
2596
2763
  exports.requestAccounts = requestAccounts;
2597
2764
  exports.requireProvider = requireProvider;
2765
+ exports.resolveUcanAuthorization = resolveUcanAuthorization;
2598
2766
  exports.resolveWalletAccount = resolveWalletAccount;
2599
2767
  exports.setAccessToken = setAccessToken;
2600
2768
  exports.setCentralSessionToken = setCentralSessionToken;