@yeying-community/web3-bs 1.0.15 → 1.0.17

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 CHANGED
@@ -26,6 +26,7 @@ npm install @yeying-community/web3-bs
26
26
  - `getChainId` / `getBalance`
27
27
  - `onAccountsChanged` / `onChainChanged`
28
28
  - `classifyWalletError` / `isUserRejectedWalletAction` / `isWalletReconnectError`
29
+ - `connectAndGetWalletProfile` / `requestWalletProfilePermission` / `getWalletProfile`
29
30
 
30
31
  `requestAccounts` 默认会复用同一 provider 上尚未完成的连接请求,避免用户重复点击时触发多个钱包授权弹窗。
31
32
  当钱包已经存在待确认的连接、签名或解锁窗口时,可调用 `focusPendingApproval` 将该窗口重新拉到前台,而不是再发起一次新的请求。
@@ -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 {
@@ -4,3 +4,4 @@ export * from './siwe';
4
4
  export * from './ucan';
5
5
  export * from './central';
6
6
  export * from './encrypt';
7
+ export * from './profile';
@@ -0,0 +1,34 @@
1
+ import type { Eip1193Provider } from './types';
2
+ export type WalletProfileField = 'username' | 'email';
3
+ export type WalletProfile = Partial<Record<WalletProfileField, string>>;
4
+ export type WalletProfilePermission = {
5
+ parentCapability: 'yeying_profile';
6
+ caveats?: Array<{
7
+ type?: string;
8
+ value?: WalletProfileField[] | {
9
+ fields?: WalletProfileField[];
10
+ [key: string]: unknown;
11
+ };
12
+ [key: string]: unknown;
13
+ }>;
14
+ date?: number;
15
+ [key: string]: unknown;
16
+ };
17
+ export type WalletProfileResult = {
18
+ address: string;
19
+ chainId: string | null;
20
+ profile: WalletProfile;
21
+ };
22
+ export type WalletProfileOptions = {
23
+ provider?: Eip1193Provider;
24
+ fields: WalletProfileField[];
25
+ };
26
+ export type ConnectWalletProfileOptions = WalletProfileOptions & {
27
+ requestPermission?: boolean;
28
+ };
29
+ export declare function getGrantedProfileFields(permission: WalletProfilePermission | null): WalletProfileField[];
30
+ export declare function getWalletProfilePermission(provider?: Eip1193Provider): Promise<WalletProfilePermission | null>;
31
+ export declare function requestWalletProfilePermission(options: WalletProfileOptions): Promise<WalletProfilePermission>;
32
+ export declare function getWalletProfile(options: WalletProfileOptions): Promise<WalletProfileResult>;
33
+ export declare function revokeWalletProfilePermission(provider?: Eip1193Provider): Promise<void>;
34
+ export declare function connectAndGetWalletProfile(options: ConnectWalletProfileOptions): Promise<WalletProfileResult>;
@@ -2036,7 +2036,8 @@ async function authCentralUcanFetch(input, init = {}, options = {}) {
2036
2036
  * 调用钱包插件的 `yeying_encrypt` / `yeying_decrypt` / `yeying_getCipherSuites`
2037
2037
  * EIP-1193 自定义方法。命名安全套件 + 静默执行 + 站点授权模型同 UCAN。
2038
2038
  *
2039
- * 数据密码(password 参数)由 DApp 自行管理与钱包密码独立;
2039
+ * 默认数据密码(password 参数)由 DApp 自行管理与钱包密码独立;
2040
+ * 也可通过 passwordSource 请求钱包插件在钱包内部派生加密密码。
2040
2041
  * plaintext 走 base64 字符串跨 message 边界传输。
2041
2042
  */
2042
2043
  class CipherError extends Error {
@@ -2087,6 +2088,8 @@ async function encrypt(options) {
2087
2088
  params: [{
2088
2089
  data: options.data,
2089
2090
  password: options.password,
2091
+ passwordSource: options.passwordSource,
2092
+ passwordContext: options.passwordContext,
2090
2093
  suite: options.suite
2091
2094
  }]
2092
2095
  });
@@ -2110,7 +2113,9 @@ async function decrypt(options) {
2110
2113
  method: 'yeying_decrypt',
2111
2114
  params: [{
2112
2115
  ciphertext: options.ciphertext,
2113
- password: options.password
2116
+ password: options.password,
2117
+ passwordSource: options.passwordSource,
2118
+ passwordContext: options.passwordContext
2114
2119
  }]
2115
2120
  });
2116
2121
  if (!result || typeof result !== 'object' || typeof result.plaintext !== 'string') {
@@ -2146,6 +2151,111 @@ async function getSupportedCipherSuites(options = {}) {
2146
2151
  }
2147
2152
  }
2148
2153
 
2154
+ const SUPPORTED_FIELDS = new Set(['username', 'email']);
2155
+ function normalizeFields(fields) {
2156
+ if (!Array.isArray(fields) || fields.length === 0) {
2157
+ throw new Error('Profile fields must contain username and/or email');
2158
+ }
2159
+ const normalized = Array.from(new Set(fields.map(field => String(field))));
2160
+ if (normalized.some(field => !SUPPORTED_FIELDS.has(field))) {
2161
+ throw new Error('Unsupported wallet profile field');
2162
+ }
2163
+ return normalized;
2164
+ }
2165
+ function parsePermission(value) {
2166
+ if (!value || typeof value !== 'object')
2167
+ return null;
2168
+ const permission = value;
2169
+ return permission.parentCapability === 'yeying_profile' ? permission : null;
2170
+ }
2171
+ function getGrantedProfileFields(permission) {
2172
+ if (!permission || !Array.isArray(permission.caveats))
2173
+ return [];
2174
+ const fields = permission.caveats.flatMap(caveat => {
2175
+ if (Array.isArray(caveat?.value))
2176
+ return caveat.value;
2177
+ return Array.isArray(caveat?.value?.fields) ? caveat.value.fields : [];
2178
+ });
2179
+ return Array.from(new Set(fields.filter(field => SUPPORTED_FIELDS.has(field))));
2180
+ }
2181
+ async function getWalletProfilePermission(provider) {
2182
+ const target = provider || (await requireProvider());
2183
+ const permissions = await target.request({ method: 'wallet_getPermissions' });
2184
+ if (!Array.isArray(permissions))
2185
+ return null;
2186
+ return permissions.map(parsePermission).find(Boolean) || null;
2187
+ }
2188
+ async function requestWalletProfilePermission(options) {
2189
+ const fields = normalizeFields(options.fields);
2190
+ const provider = options.provider || (await requireProvider());
2191
+ const result = await provider.request({
2192
+ method: 'wallet_requestPermissions',
2193
+ params: [{ yeying_profile: { fields } }],
2194
+ });
2195
+ if (!Array.isArray(result)) {
2196
+ throw new Error('Wallet returned an invalid profile permission response');
2197
+ }
2198
+ const permission = result.map(parsePermission).find(Boolean);
2199
+ if (!permission)
2200
+ throw new Error('Wallet did not grant profile permission');
2201
+ const granted = new Set(getGrantedProfileFields(permission));
2202
+ if (fields.some(field => !granted.has(field))) {
2203
+ throw new Error('Wallet did not grant all requested profile fields');
2204
+ }
2205
+ return permission;
2206
+ }
2207
+ async function getWalletProfile(options) {
2208
+ const fields = normalizeFields(options.fields);
2209
+ const provider = options.provider || (await requireProvider());
2210
+ const result = await provider.request({
2211
+ method: 'yeying_getProfile',
2212
+ params: [{ fields }],
2213
+ });
2214
+ if (!result || typeof result !== 'object') {
2215
+ throw new Error('Wallet returned an invalid profile response');
2216
+ }
2217
+ const value = result;
2218
+ const profileSource = value.profile;
2219
+ if (typeof value.address !== 'string' || !profileSource || typeof profileSource !== 'object') {
2220
+ throw new Error('Wallet returned an invalid profile response');
2221
+ }
2222
+ const profile = {};
2223
+ for (const field of fields) {
2224
+ const fieldValue = profileSource[field];
2225
+ if (typeof fieldValue === 'string')
2226
+ profile[field] = fieldValue;
2227
+ }
2228
+ return {
2229
+ address: value.address,
2230
+ chainId: typeof value.chainId === 'string' ? value.chainId : null,
2231
+ profile,
2232
+ };
2233
+ }
2234
+ async function revokeWalletProfilePermission(provider) {
2235
+ const target = provider || (await requireProvider());
2236
+ await target.request({
2237
+ method: 'wallet_revokePermissions',
2238
+ params: [{ yeying_profile: {} }],
2239
+ });
2240
+ }
2241
+ async function connectAndGetWalletProfile(options) {
2242
+ const fields = normalizeFields(options.fields);
2243
+ const provider = options.provider || (await requireProvider());
2244
+ const accounts = await provider.request({ method: 'eth_requestAccounts' });
2245
+ if (!Array.isArray(accounts) || typeof accounts[0] !== 'string') {
2246
+ throw new Error('Wallet did not return an account');
2247
+ }
2248
+ if (options.requestPermission !== false) {
2249
+ const permission = await getWalletProfilePermission(provider);
2250
+ const granted = new Set(getGrantedProfileFields(permission));
2251
+ const missing = fields.filter(field => !granted.has(field));
2252
+ if (missing.length > 0) {
2253
+ await requestWalletProfilePermission({ provider, fields: missing });
2254
+ }
2255
+ }
2256
+ return getWalletProfile({ provider, fields });
2257
+ }
2258
+
2149
2259
  function normalizeBaseUrl(baseUrl) {
2150
2260
  return baseUrl.replace(/\/+$/, '');
2151
2261
  }
@@ -2691,5 +2801,5 @@ async function initDappSession(options) {
2691
2801
  return result;
2692
2802
  }
2693
2803
 
2694
- 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 };
2804
+ 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, connectAndGetWalletProfile, createAndIssueCentralUcan, createCentralSession, createDelegationUcan, createInvocationUcan, createRootUcan, createUcanSession, createWebDavClient, decodeUcanPayload, decrypt, deriveAppIdFromHost, deriveAppIdFromLocation, encrypt, focusPendingApproval, getAccessToken, getAccounts, getBalance, getCapabilityAction, getCapabilityResource, getCentralIssuerInfo, getCentralSessionToken, getChainId, getGrantedProfileFields, getOrCreateInvocationUcan, getOrCreateUcanRoot, getPreferredAccount, getProvider, getStoredUcanRoot, getSupportedCipherSuites, getUcanSession, getUcanTokenTiming, getWalletErrorCode, getWalletErrorMessage, getWalletProfile, getWalletProfilePermission, initDappSession, initWebDavStorage, isUcanTokenFresh, isUserRejectedWalletAction, isWalletReconnectError, isYeYingProvider, issueCentralUcan, loginWithChallenge, logout, normalizeAppHostnameForAppId, normalizeUcanCapabilities, normalizeUcanCapability, normalizeUcanExpiry, onAccountsChanged, onChainChanged, parseUcanAccountFromIssuer, refreshAccessToken, requestAccounts, requestWalletProfilePermission, requireProvider, resolveUcanAuthorization, resolveWalletAccount, revokeWalletProfilePermission, setAccessToken, setCentralSessionToken, signMessage, storeUcanRoot, watchAccounts, watchProvider };
2695
2805
  //# sourceMappingURL=web3-bs.esm.js.map