@yeying-community/web3-bs 1.0.13 → 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.
- package/README.md +9 -1
- package/dist/auth/provider.d.ts +2 -1
- package/dist/auth/types.d.ts +29 -0
- package/dist/auth/ucan.d.ts +28 -0
- package/dist/web3-bs.esm.js +221 -1
- package/dist/web3-bs.esm.js.map +1 -1
- package/dist/web3-bs.umd.js +223 -0
- package/dist/web3-bs.umd.js.map +1 -1
- package/package.json +1 -1
package/dist/web3-bs.umd.js
CHANGED
|
@@ -79,6 +79,17 @@
|
|
|
79
79
|
}
|
|
80
80
|
return accounts[0] || null;
|
|
81
81
|
}
|
|
82
|
+
function normalizeAccount(account) {
|
|
83
|
+
const normalized = (account || '').trim();
|
|
84
|
+
return normalized || null;
|
|
85
|
+
}
|
|
86
|
+
function isSameAccount(left, right) {
|
|
87
|
+
const normalizedLeft = normalizeAccount(left);
|
|
88
|
+
const normalizedRight = normalizeAccount(right);
|
|
89
|
+
return Boolean(normalizedLeft &&
|
|
90
|
+
normalizedRight &&
|
|
91
|
+
normalizedLeft.toLowerCase() === normalizedRight.toLowerCase());
|
|
92
|
+
}
|
|
82
93
|
function isYeYingProvider(provider, info) {
|
|
83
94
|
if (!provider)
|
|
84
95
|
return false;
|
|
@@ -342,6 +353,49 @@
|
|
|
342
353
|
writeStoredAccount(storageKey, account);
|
|
343
354
|
return { account, accounts };
|
|
344
355
|
}
|
|
356
|
+
async function resolveWalletAccount(options = {}) {
|
|
357
|
+
const provider = options.provider || (await requireProvider());
|
|
358
|
+
let accounts = await getAccounts(provider);
|
|
359
|
+
if (accounts.length === 0 && options.autoConnect) {
|
|
360
|
+
accounts = await requestAccounts({ provider });
|
|
361
|
+
}
|
|
362
|
+
const expectedAccount = normalizeAccount(options.expectedAccount);
|
|
363
|
+
const walletAccount = normalizeAccount(accounts[0]);
|
|
364
|
+
if (!walletAccount) {
|
|
365
|
+
return {
|
|
366
|
+
status: 'unavailable',
|
|
367
|
+
account: null,
|
|
368
|
+
walletAccount: null,
|
|
369
|
+
expectedAccount,
|
|
370
|
+
accounts,
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
if (!expectedAccount) {
|
|
374
|
+
return {
|
|
375
|
+
status: 'wallet',
|
|
376
|
+
account: walletAccount,
|
|
377
|
+
walletAccount,
|
|
378
|
+
expectedAccount: null,
|
|
379
|
+
accounts,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
if (isSameAccount(expectedAccount, walletAccount)) {
|
|
383
|
+
return {
|
|
384
|
+
status: 'matched',
|
|
385
|
+
account: walletAccount,
|
|
386
|
+
walletAccount,
|
|
387
|
+
expectedAccount,
|
|
388
|
+
accounts,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
return {
|
|
392
|
+
status: 'mismatch',
|
|
393
|
+
account: null,
|
|
394
|
+
walletAccount,
|
|
395
|
+
expectedAccount,
|
|
396
|
+
accounts,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
345
399
|
function watchAccounts(provider, handler, options = {}) {
|
|
346
400
|
const storageKey = options.storageKey || DEFAULT_ACCOUNT_STORAGE_KEY;
|
|
347
401
|
const preferStored = options.preferStored !== false;
|
|
@@ -816,6 +870,73 @@
|
|
|
816
870
|
function normalizeUcanExpiry(exp, fallbackMs) {
|
|
817
871
|
return normalizeExpiry(exp, fallbackMs);
|
|
818
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
|
+
}
|
|
819
940
|
function decodeUcanPayload(token) {
|
|
820
941
|
const parts = String(token || '').split('.');
|
|
821
942
|
if (parts.length < 2)
|
|
@@ -1243,6 +1364,105 @@
|
|
|
1243
1364
|
function isRootExpired(root, nowMs) {
|
|
1244
1365
|
return Boolean(root.exp && nowMs > root.exp);
|
|
1245
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
|
+
}
|
|
1246
1466
|
async function getOrCreateUcanRoot(options) {
|
|
1247
1467
|
const provider = options.provider || (await requireProvider());
|
|
1248
1468
|
const session = options.session || (await createUcanSession({ id: options.sessionId, provider }));
|
|
@@ -2538,9 +2758,12 @@
|
|
|
2538
2758
|
exports.normalizeUcanExpiry = normalizeUcanExpiry;
|
|
2539
2759
|
exports.onAccountsChanged = onAccountsChanged;
|
|
2540
2760
|
exports.onChainChanged = onChainChanged;
|
|
2761
|
+
exports.parseUcanAccountFromIssuer = parseUcanAccountFromIssuer;
|
|
2541
2762
|
exports.refreshAccessToken = refreshAccessToken;
|
|
2542
2763
|
exports.requestAccounts = requestAccounts;
|
|
2543
2764
|
exports.requireProvider = requireProvider;
|
|
2765
|
+
exports.resolveUcanAuthorization = resolveUcanAuthorization;
|
|
2766
|
+
exports.resolveWalletAccount = resolveWalletAccount;
|
|
2544
2767
|
exports.setAccessToken = setAccessToken;
|
|
2545
2768
|
exports.setCentralSessionToken = setCentralSessionToken;
|
|
2546
2769
|
exports.signMessage = signMessage;
|