@yeying-community/web3-bs 1.0.14 → 1.0.16
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/auth/encrypt.d.ts +9 -3
- package/dist/auth/ucan.d.ts +28 -0
- package/dist/web3-bs.esm.js +174 -3
- package/dist/web3-bs.esm.js.map +1 -1
- package/dist/web3-bs.umd.js +175 -2
- package/dist/web3-bs.umd.js.map +1 -1
- package/package.json +1 -1
package/dist/web3-bs.umd.js
CHANGED
|
@@ -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 }));
|
|
@@ -1876,7 +2042,8 @@
|
|
|
1876
2042
|
* 调用钱包插件的 `yeying_encrypt` / `yeying_decrypt` / `yeying_getCipherSuites`
|
|
1877
2043
|
* EIP-1193 自定义方法。命名安全套件 + 静默执行 + 站点授权模型同 UCAN。
|
|
1878
2044
|
*
|
|
1879
|
-
*
|
|
2045
|
+
* 默认数据密码(password 参数)由 DApp 自行管理与钱包密码独立;
|
|
2046
|
+
* 也可通过 passwordSource 请求钱包插件在钱包内部派生加密密码。
|
|
1880
2047
|
* plaintext 走 base64 字符串跨 message 边界传输。
|
|
1881
2048
|
*/
|
|
1882
2049
|
class CipherError extends Error {
|
|
@@ -1927,6 +2094,8 @@
|
|
|
1927
2094
|
params: [{
|
|
1928
2095
|
data: options.data,
|
|
1929
2096
|
password: options.password,
|
|
2097
|
+
passwordSource: options.passwordSource,
|
|
2098
|
+
passwordContext: options.passwordContext,
|
|
1930
2099
|
suite: options.suite
|
|
1931
2100
|
}]
|
|
1932
2101
|
});
|
|
@@ -1950,7 +2119,9 @@
|
|
|
1950
2119
|
method: 'yeying_decrypt',
|
|
1951
2120
|
params: [{
|
|
1952
2121
|
ciphertext: options.ciphertext,
|
|
1953
|
-
password: options.password
|
|
2122
|
+
password: options.password,
|
|
2123
|
+
passwordSource: options.passwordSource,
|
|
2124
|
+
passwordContext: options.passwordContext
|
|
1954
2125
|
}]
|
|
1955
2126
|
});
|
|
1956
2127
|
if (!result || typeof result !== 'object' || typeof result.plaintext !== 'string') {
|
|
@@ -2592,9 +2763,11 @@
|
|
|
2592
2763
|
exports.normalizeUcanExpiry = normalizeUcanExpiry;
|
|
2593
2764
|
exports.onAccountsChanged = onAccountsChanged;
|
|
2594
2765
|
exports.onChainChanged = onChainChanged;
|
|
2766
|
+
exports.parseUcanAccountFromIssuer = parseUcanAccountFromIssuer;
|
|
2595
2767
|
exports.refreshAccessToken = refreshAccessToken;
|
|
2596
2768
|
exports.requestAccounts = requestAccounts;
|
|
2597
2769
|
exports.requireProvider = requireProvider;
|
|
2770
|
+
exports.resolveUcanAuthorization = resolveUcanAuthorization;
|
|
2598
2771
|
exports.resolveWalletAccount = resolveWalletAccount;
|
|
2599
2772
|
exports.setAccessToken = setAccessToken;
|
|
2600
2773
|
exports.setCentralSessionToken = setCentralSessionToken;
|