@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.
@@ -4,7 +4,8 @@
4
4
  * 调用钱包插件的 `yeying_encrypt` / `yeying_decrypt` / `yeying_getCipherSuites`
5
5
  * EIP-1193 自定义方法。命名安全套件 + 静默执行 + 站点授权模型同 UCAN。
6
6
  *
7
- * 数据密码(password 参数)由 DApp 自行管理与钱包密码独立;
7
+ * 默认数据密码(password 参数)由 DApp 自行管理与钱包密码独立;
8
+ * 也可通过 passwordSource 请求钱包插件在钱包内部派生加密密码。
8
9
  * plaintext 走 base64 字符串跨 message 边界传输。
9
10
  */
10
11
  import { isUserRejectedWalletAction } from './provider';
@@ -14,15 +15,20 @@ export interface CipherSuiteInfo {
14
15
  description: string;
15
16
  mode: 'hash' | 'symmetric';
16
17
  }
18
+ export type CipherPasswordSource = 'manual' | 'wallet' | 'wallet+password';
17
19
  export interface EncryptOptions {
18
20
  data: string | Uint8Array;
19
- password: string;
21
+ password?: string;
22
+ passwordSource?: CipherPasswordSource;
23
+ passwordContext?: string;
20
24
  suite?: string;
21
25
  provider?: Eip1193Provider;
22
26
  }
23
27
  export interface DecryptOptions {
24
28
  ciphertext: string;
25
- password: string;
29
+ password?: string;
30
+ passwordSource?: CipherPasswordSource;
31
+ passwordContext?: string;
26
32
  provider?: Eip1193Provider;
27
33
  }
28
34
  export interface GetCipherSuitesOptions {
@@ -120,6 +120,32 @@ export type UcanAuthErrorInfo = {
120
120
  status?: number;
121
121
  code?: string | number;
122
122
  };
123
+ export type ResolveUcanAuthorizationReason = 'missing_root' | 'expired' | 'not_before' | 'missing_account' | 'invalid_issuer' | 'issuer_mismatch' | 'capability_mismatch' | 'audience_mismatch' | 'service_host_mismatch';
124
+ export type ResolveUcanAuthorizationOptions = {
125
+ sessionId?: string;
126
+ root?: UcanRootProof | null;
127
+ currentAccount?: string | null;
128
+ expectedCapabilities?: UcanCapability[];
129
+ expectedAudience?: string | null;
130
+ expectedServiceHosts?: Record<string, string | null | undefined>;
131
+ recoverAccountFromRoot?: boolean;
132
+ nowMs?: number;
133
+ };
134
+ export type ResolveUcanAuthorizationResult = {
135
+ status: 'authorized';
136
+ account: string;
137
+ root: UcanRootProof;
138
+ restoredAccount: boolean;
139
+ expiresAt: number;
140
+ } | {
141
+ status: 'unauthorized';
142
+ reason: ResolveUcanAuthorizationReason;
143
+ root?: UcanRootProof | null;
144
+ account?: string | null;
145
+ expiresAt?: number;
146
+ expected?: string;
147
+ actual?: string;
148
+ };
123
149
  export declare const DEFAULT_UCAN_SESSION_TTL_MS: number;
124
150
  export declare const DEFAULT_UCAN_TOKEN_TTL_MS: number;
125
151
  export declare const DEFAULT_UCAN_TOKEN_SKEW_MS: number;
@@ -132,6 +158,7 @@ export declare function normalizeUcanCapabilities(caps: UcanCapability[] | undef
132
158
  includeLegacyAliases?: boolean;
133
159
  }): UcanCapability[];
134
160
  export declare function normalizeUcanExpiry(exp: number | undefined, fallbackMs: number): number;
161
+ export declare function parseUcanAccountFromIssuer(issuer?: string | null): string | null;
135
162
  export declare function decodeUcanPayload(token: string): UcanTokenPayload | null;
136
163
  export declare function getUcanTokenTiming(token: string, options?: {
137
164
  nowMs?: number;
@@ -145,6 +172,7 @@ export declare function createUcanSession(options?: CreateUcanSessionOptions): P
145
172
  export declare function clearUcanSession(id?: string): Promise<void>;
146
173
  export declare function storeUcanRoot(root: UcanRootProof, id?: string): Promise<void>;
147
174
  export declare function getStoredUcanRoot(id?: string): Promise<UcanRootProof | null>;
175
+ export declare function resolveUcanAuthorization(options?: ResolveUcanAuthorizationOptions): Promise<ResolveUcanAuthorizationResult>;
148
176
  export declare function getOrCreateUcanRoot(options: CreateRootUcanOptions): Promise<UcanRootProof>;
149
177
  export declare function createRootUcan(options: CreateRootUcanOptions): Promise<UcanRootProof>;
150
178
  export declare function createDelegationUcan(options: CreateUcanTokenOptions): Promise<string>;
@@ -864,6 +864,73 @@ function normalizeExpiry(exp, fallbackMs) {
864
864
  function normalizeUcanExpiry(exp, fallbackMs) {
865
865
  return normalizeExpiry(exp, fallbackMs);
866
866
  }
867
+ function normalizeEthAccount(account) {
868
+ return String(account || '').trim().toLowerCase();
869
+ }
870
+ function parseUcanAccountFromIssuer(issuer) {
871
+ const normalized = String(issuer || '').trim().toLowerCase();
872
+ const prefix = 'did:pkh:eth:';
873
+ if (!normalized.startsWith(prefix))
874
+ return null;
875
+ const account = normalized.slice(prefix.length);
876
+ return account || null;
877
+ }
878
+ function getUcanIssuerForAccount(account) {
879
+ return `did:pkh:eth:${normalizeEthAccount(account)}`;
880
+ }
881
+ function extractUcanStatementPayload(message) {
882
+ if (!message || typeof message !== 'string')
883
+ return null;
884
+ const marker = 'UCAN-AUTH';
885
+ const index = message.indexOf(marker);
886
+ if (index < 0)
887
+ return null;
888
+ const jsonStart = message.indexOf('{', index + marker.length);
889
+ const jsonEnd = message.lastIndexOf('}');
890
+ if (jsonStart < 0 || jsonEnd < jsonStart)
891
+ return null;
892
+ try {
893
+ const parsed = JSON.parse(message.slice(jsonStart, jsonEnd + 1));
894
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
895
+ return null;
896
+ }
897
+ return parsed;
898
+ }
899
+ catch {
900
+ return null;
901
+ }
902
+ }
903
+ function getUcanRootServiceHosts(root) {
904
+ const payload = extractUcanStatementPayload(root.siwe?.message);
905
+ const hosts = payload?.service_hosts;
906
+ if (!hosts || typeof hosts !== 'object' || Array.isArray(hosts)) {
907
+ return null;
908
+ }
909
+ return hosts;
910
+ }
911
+ function getServiceHostMismatch(root, expectedServiceHosts) {
912
+ if (!expectedServiceHosts)
913
+ return null;
914
+ const entries = Object.entries(expectedServiceHosts)
915
+ .map(([key, value]) => [key, String(value || '').trim()])
916
+ .filter(([, value]) => Boolean(value));
917
+ if (!entries.length)
918
+ return null;
919
+ const hosts = getUcanRootServiceHosts(root);
920
+ if (!hosts) {
921
+ return {
922
+ expected: entries.map(([key, value]) => `${key}:${value}`).join('|'),
923
+ actual: '',
924
+ };
925
+ }
926
+ for (const [key, expected] of entries) {
927
+ const actual = typeof hosts[key] === 'string' ? hosts[key].trim() : '';
928
+ if (actual !== expected) {
929
+ return { expected, actual };
930
+ }
931
+ }
932
+ return null;
933
+ }
867
934
  function decodeUcanPayload(token) {
868
935
  const parts = String(token || '').split('.');
869
936
  if (parts.length < 2)
@@ -1291,6 +1358,105 @@ function capsEqual(a, b) {
1291
1358
  function isRootExpired(root, nowMs) {
1292
1359
  return Boolean(root.exp && nowMs > root.exp);
1293
1360
  }
1361
+ async function resolveUcanAuthorization(options = {}) {
1362
+ const root = options.root === undefined
1363
+ ? await getStoredUcanRoot(options.sessionId || DEFAULT_SESSION_ID)
1364
+ : options.root;
1365
+ const nowMs = options.nowMs ?? Date.now();
1366
+ if (!root) {
1367
+ return { status: 'unauthorized', reason: 'missing_root', root };
1368
+ }
1369
+ if (typeof root.exp !== 'number' || root.exp <= nowMs) {
1370
+ return {
1371
+ status: 'unauthorized',
1372
+ reason: 'expired',
1373
+ root,
1374
+ expiresAt: root.exp,
1375
+ };
1376
+ }
1377
+ if (typeof root.nbf === 'number' && root.nbf > nowMs) {
1378
+ return {
1379
+ status: 'unauthorized',
1380
+ reason: 'not_before',
1381
+ root,
1382
+ expiresAt: root.exp,
1383
+ };
1384
+ }
1385
+ const accountFromIssuer = parseUcanAccountFromIssuer(root.iss);
1386
+ if (!accountFromIssuer) {
1387
+ return {
1388
+ status: 'unauthorized',
1389
+ reason: 'invalid_issuer',
1390
+ root,
1391
+ expiresAt: root.exp,
1392
+ actual: root.iss,
1393
+ };
1394
+ }
1395
+ const currentAccount = normalizeEthAccount(options.currentAccount);
1396
+ if (!currentAccount && !options.recoverAccountFromRoot) {
1397
+ return {
1398
+ status: 'unauthorized',
1399
+ reason: 'missing_account',
1400
+ root,
1401
+ account: null,
1402
+ expiresAt: root.exp,
1403
+ };
1404
+ }
1405
+ const account = currentAccount || accountFromIssuer;
1406
+ const expectedIssuer = getUcanIssuerForAccount(account);
1407
+ if (root.iss !== expectedIssuer) {
1408
+ return {
1409
+ status: 'unauthorized',
1410
+ reason: 'issuer_mismatch',
1411
+ root,
1412
+ account,
1413
+ expiresAt: root.exp,
1414
+ expected: expectedIssuer,
1415
+ actual: root.iss,
1416
+ };
1417
+ }
1418
+ if (options.expectedCapabilities &&
1419
+ !capsEqual(root.cap, options.expectedCapabilities)) {
1420
+ return {
1421
+ status: 'unauthorized',
1422
+ reason: 'capability_mismatch',
1423
+ root,
1424
+ account,
1425
+ expiresAt: root.exp,
1426
+ };
1427
+ }
1428
+ const expectedAudience = String(options.expectedAudience || '').trim();
1429
+ if (expectedAudience && root.aud !== expectedAudience) {
1430
+ return {
1431
+ status: 'unauthorized',
1432
+ reason: 'audience_mismatch',
1433
+ root,
1434
+ account,
1435
+ expiresAt: root.exp,
1436
+ expected: expectedAudience,
1437
+ actual: root.aud,
1438
+ };
1439
+ }
1440
+ const serviceHostMismatch = getServiceHostMismatch(root, options.expectedServiceHosts);
1441
+ if (serviceHostMismatch) {
1442
+ return {
1443
+ status: 'unauthorized',
1444
+ reason: 'service_host_mismatch',
1445
+ root,
1446
+ account,
1447
+ expiresAt: root.exp,
1448
+ expected: serviceHostMismatch.expected,
1449
+ actual: serviceHostMismatch.actual,
1450
+ };
1451
+ }
1452
+ return {
1453
+ status: 'authorized',
1454
+ account,
1455
+ root,
1456
+ restoredAccount: !currentAccount && account === accountFromIssuer,
1457
+ expiresAt: root.exp,
1458
+ };
1459
+ }
1294
1460
  async function getOrCreateUcanRoot(options) {
1295
1461
  const provider = options.provider || (await requireProvider());
1296
1462
  const session = options.session || (await createUcanSession({ id: options.sessionId, provider }));
@@ -1870,7 +2036,8 @@ async function authCentralUcanFetch(input, init = {}, options = {}) {
1870
2036
  * 调用钱包插件的 `yeying_encrypt` / `yeying_decrypt` / `yeying_getCipherSuites`
1871
2037
  * EIP-1193 自定义方法。命名安全套件 + 静默执行 + 站点授权模型同 UCAN。
1872
2038
  *
1873
- * 数据密码(password 参数)由 DApp 自行管理与钱包密码独立;
2039
+ * 默认数据密码(password 参数)由 DApp 自行管理与钱包密码独立;
2040
+ * 也可通过 passwordSource 请求钱包插件在钱包内部派生加密密码。
1874
2041
  * plaintext 走 base64 字符串跨 message 边界传输。
1875
2042
  */
1876
2043
  class CipherError extends Error {
@@ -1921,6 +2088,8 @@ async function encrypt(options) {
1921
2088
  params: [{
1922
2089
  data: options.data,
1923
2090
  password: options.password,
2091
+ passwordSource: options.passwordSource,
2092
+ passwordContext: options.passwordContext,
1924
2093
  suite: options.suite
1925
2094
  }]
1926
2095
  });
@@ -1944,7 +2113,9 @@ async function decrypt(options) {
1944
2113
  method: 'yeying_decrypt',
1945
2114
  params: [{
1946
2115
  ciphertext: options.ciphertext,
1947
- password: options.password
2116
+ password: options.password,
2117
+ passwordSource: options.passwordSource,
2118
+ passwordContext: options.passwordContext
1948
2119
  }]
1949
2120
  });
1950
2121
  if (!result || typeof result !== 'object' || typeof result.plaintext !== 'string') {
@@ -2525,5 +2696,5 @@ async function initDappSession(options) {
2525
2696
  return result;
2526
2697
  }
2527
2698
 
2528
- export { CipherError, DEFAULT_UCAN_SESSION_TTL_MS, DEFAULT_UCAN_TOKEN_SKEW_MS, DEFAULT_UCAN_TOKEN_TTL_MS, WebDavClient, authCentralUcanFetch, authFetch, authUcanFetch, base64ToBytes, bytesToBase64, classifyUcanAuthError, classifyWalletError, clearAccessToken, clearCentralSessionToken, clearUcanSession, createAndIssueCentralUcan, createCentralSession, createDelegationUcan, createInvocationUcan, createRootUcan, createUcanSession, createWebDavClient, decodeUcanPayload, decrypt, deriveAppIdFromHost, deriveAppIdFromLocation, encrypt, focusPendingApproval, getAccessToken, getAccounts, getBalance, getCapabilityAction, getCapabilityResource, getCentralIssuerInfo, getCentralSessionToken, getChainId, getOrCreateInvocationUcan, getOrCreateUcanRoot, getPreferredAccount, getProvider, getStoredUcanRoot, getSupportedCipherSuites, getUcanSession, getUcanTokenTiming, getWalletErrorCode, getWalletErrorMessage, initDappSession, initWebDavStorage, isUcanTokenFresh, isUserRejectedWalletAction, isWalletReconnectError, isYeYingProvider, issueCentralUcan, loginWithChallenge, logout, normalizeAppHostnameForAppId, normalizeUcanCapabilities, normalizeUcanCapability, normalizeUcanExpiry, onAccountsChanged, onChainChanged, refreshAccessToken, requestAccounts, requireProvider, resolveWalletAccount, setAccessToken, setCentralSessionToken, signMessage, storeUcanRoot, watchAccounts, watchProvider };
2699
+ export { CipherError, DEFAULT_UCAN_SESSION_TTL_MS, DEFAULT_UCAN_TOKEN_SKEW_MS, DEFAULT_UCAN_TOKEN_TTL_MS, WebDavClient, authCentralUcanFetch, authFetch, authUcanFetch, base64ToBytes, bytesToBase64, classifyUcanAuthError, classifyWalletError, clearAccessToken, clearCentralSessionToken, clearUcanSession, createAndIssueCentralUcan, createCentralSession, createDelegationUcan, createInvocationUcan, createRootUcan, createUcanSession, createWebDavClient, decodeUcanPayload, decrypt, deriveAppIdFromHost, deriveAppIdFromLocation, encrypt, focusPendingApproval, getAccessToken, getAccounts, getBalance, getCapabilityAction, getCapabilityResource, getCentralIssuerInfo, getCentralSessionToken, getChainId, getOrCreateInvocationUcan, getOrCreateUcanRoot, getPreferredAccount, getProvider, getStoredUcanRoot, getSupportedCipherSuites, getUcanSession, getUcanTokenTiming, getWalletErrorCode, getWalletErrorMessage, initDappSession, initWebDavStorage, isUcanTokenFresh, isUserRejectedWalletAction, isWalletReconnectError, isYeYingProvider, issueCentralUcan, loginWithChallenge, logout, normalizeAppHostnameForAppId, normalizeUcanCapabilities, normalizeUcanCapability, normalizeUcanExpiry, onAccountsChanged, onChainChanged, parseUcanAccountFromIssuer, refreshAccessToken, requestAccounts, requireProvider, resolveUcanAuthorization, resolveWalletAccount, setAccessToken, setCentralSessionToken, signMessage, storeUcanRoot, watchAccounts, watchProvider };
2529
2700
  //# sourceMappingURL=web3-bs.esm.js.map