@yeying-community/web3-bs 1.0.16 → 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,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>;
@@ -2151,6 +2151,111 @@ async function getSupportedCipherSuites(options = {}) {
2151
2151
  }
2152
2152
  }
2153
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
+
2154
2259
  function normalizeBaseUrl(baseUrl) {
2155
2260
  return baseUrl.replace(/\/+$/, '');
2156
2261
  }
@@ -2696,5 +2801,5 @@ async function initDappSession(options) {
2696
2801
  return result;
2697
2802
  }
2698
2803
 
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 };
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 };
2700
2805
  //# sourceMappingURL=web3-bs.esm.js.map