@idos-network/client 4.0.0 → 5.0.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/enclave/iframe-enclave.ts","../src/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/enclave/iframe-enclave.ts","../src/index.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{buildEphemeralSignedCredentialContentReference as e,buildPreliminaryIDOSCredential as t,mapPreliminaryToIDOSCredential as n,matchClaims as r,matchLevelOrHigher as i,recordFilter as a}from"@idos-network/credentials/utils";import{createClientKwilSigner as o,createKgwAuthenticatedBlobGateway as s,createNodeKwilClient as c,createWebKwilClient as l,isMmTokenAuth as u,mmTokenStorageId as d,signNearMessage as f}from"@idos-network/kwil-infra";import{addAttribute as p,addWallet as m,addWalletMessage as h,addWallets as ee,createPreliminaryCredential as g,credentialBroaderMessage as _,dwgMessage as te,getAccessGrantsGrantedCount as ne,getAccessGrantsOwned as re,getAttributes as ie,getCredentialOwned as ae,getCredentialShared as oe,getCredentials as se,getGrants as ce,getUser as le,getWallets as v,hasProfile as y,removeCredential as b,removeWallet as ue,revokeAccessGrant as de,sharePreliminaryCredential as fe,toDelegatedWriteGrantBaseParams as pe}from"@idos-network/kwil-infra/actions";import{NodeKwil as me}from"@idos-network/kwil-js";import{BlobGateway as x,BlobGatewayUploadOutcomeUnknownError as S,createBlobContentReference as he,createUkycContentReference as ge,requireAccessTokenForUkycContent as C,resolveCredentialEncryptedContent as _e}from"@idos-network/utils/blob-gateway";import{base64Decode as w,base64Encode as T,hexEncodeSha256Hash as E,utf8Decode as D}from"@idos-network/utils/codecs";import{LocalStorageStore as ve,MemoryStore as ye}from"@idos-network/utils/store";import O from"tiny-invariant";import{BaseProvider as be}from"@idos-network/enclave";var k=class extends be{container;iframe;hostUrl;bound=!1;constructor(e){if(super(e),!this.options.container)throw Error(`container is required`);this.container=this.options.container,this.hostUrl=new URL(this.options.url??`https://enclave.idos.network`),this.iframe=document.createElement(`iframe`),this.iframe.id=`idos-enclave-iframe`}async load(){await this.createAndLoadIframe(),await this.requestToEnclave(`load`),await this.reconfigure(),await this.bindMessageListener()}async reset(){throw Error(`Embedding pages cannot reset enclave storage`)}async reconfigure(e={}){super.reconfigure(e),await this.requestToEnclave(`reconfigure`,this.options)}async confirm(e){this.showEnclave();try{return await this.requestToEnclave(`confirm`,e)}catch(e){return console.error(e),!1}finally{this.hideEnclave()}}async filterCredentials(e,t){return await this.requestToEnclave(`filterCredentials`,e,t)}async encrypt(e,t){return this.requestToEnclave(`encrypt`,e,t)}async decrypt(e,t){return this.requestToEnclave(`decrypt`,e,t)}async backupUserEncryptionProfile(){this.showEnclave();try{await this.requestToEnclave(`backupUserEncryptionProfile`)}catch(e){console.error(e)}finally{this.hideEnclave()}}async ensureUserEncryptionProfile(){this.showEnclave();try{return await this.requestToEnclave(`ensureUserEncryptionProfile`)}finally{this.hideEnclave()}}async addAddressMessageToSign(e,t,n){return this.requestToEnclave(`addAddressMessageToSign`,e,t,n)}async removeAddressMessageToSign(e,t,n){return this.requestToEnclave(`removeAddressMessageToSign`,e,t,n)}async addAddressToMpcSecret(e,t,n){return this.requestToEnclave(`addAddressToMpcSecret`,e,t,n)}async removeAddressFromMpcSecret(e,t,n){return this.requestToEnclave(`removeAddressFromMpcSecret`,e,t,n)}async createAndLoadIframe(){let e=document.querySelector(this.container);if(!e)throw Error(`Can't find container with selector ${this.container}`);let t=[`publickey-credentials-get`,`storage-access`],n=[`forms`,`modals`,`popups`,`popups-to-escape-sandbox`,`same-origin`,`scripts`].map(e=>`allow-${e}`),r={"aspect-ratio":`4/1`,"background-color":`transparent`,border:`none`,display:`block`,overflow:`hidden`,width:`100%`};this.iframe.allow=t.join(`; `),this.iframe.referrerPolicy=`origin`,this.iframe.sandbox.add(...n),this.iframe.src=this.hostUrl.toString();for(let[e,t]of Object.entries(r))this.iframe.style.setProperty(e,t);let i;for(;i=document.getElementById(this.iframe.id);)console.log(`reinstalling idOS iframe...`),e.removeChild(i);return e.appendChild(this.iframe),new Promise(e=>this.iframe.addEventListener(`load`,()=>{e()},{once:!0}))}showEnclave(){this.iframe.parentElement.classList.add(`visible`)}hideEnclave(){this.iframe.parentElement.classList.remove(`visible`)}async requestToEnclave(e,...t){return new Promise((n,r)=>{let{port1:i,port2:a}=new MessageChannel;i.onmessage=({data:e})=>{i.close(),e.error?r(e.error):n(e.result)},this.iframe.contentWindow.postMessage({method:e,data:t},this.hostUrl.origin,[a])})}bindMessageListener(){this.bound||window.addEventListener(`message`,this.onMessage.bind(this)),this.bound=!0}async onMessage(e){if(!e||!e.data||typeof e.data!=`object`||e.data.type!==`idOS:signTypedData`||e.origin!==this.hostUrl.origin)return;let t=e.data.payload,n=await this.signTypedData(t.domain,t.types,t.value);await this.requestToEnclave(`signTypedDataResponse`,n)}};function A(){return typeof window<`u`}function j(e){return e.client instanceof me}function M(e){return A()?new x({url:e,fetchFn:(e,t)=>fetch(e,{...t,credentials:`include`})}):new x({url:e})}function xe(e,t){return j(e.kwilClient)?s({url:e.blobGateway.url,kwilClient:e.kwilClient,signer:t}):u(t)?e.blobGateway.withAccessToken(t.accessToken):e.blobGateway}function N(e,t){if(e===`MM`)return d(t)}function Se(e,t){return e.byteLength===t.byteLength&&e.every((e,n)=>e===t[n])}const P="This idOS client is stale: another signer was set or it was logged out. Use the client returned by the latest `withUserSigner()`.",F=new WeakMap,I=new WeakMap,L=new WeakMap,R=new WeakMap,z=new WeakMap,B=new WeakSet;function V(e){return F.get(e)??e}function H(e,t){if(e.signer!==t)throw Error(P)}function U(e,t){let n=V(e),r=t?I.get(n)?.get(t):void 0;if(r)return r;let i=()=>H(n,t),a={get signer(){return i(),n.signer},get client(){return i(),n.client},call:async(...e)=>(i(),n.call(...e)),execute:async(...e)=>(i(),n.execute(...e)),waitForTx:async e=>(i(),n.waitForTx(e)),setSigner:e=>{i(),n.setSigner(e)}};if(F.set(a,n),t){let e=I.get(n)??new WeakMap;e.set(t,a),I.set(n,e)}return a}function W(e){return e&&L.get(e)||e}function G(e,t,n){let r=W(e),i=n?R.get(r)?.get(n):void 0;if(i)return i;let a=new Proxy(r,{get(e,r){if(r===`then`||typeof r==`symbol`)return;let i=Reflect.get(e,r,e);return typeof i==`function`?(...r)=>(H(t,n),i.apply(e,r)):(H(t,n),i)}});if(L.set(a,r),n){let e=R.get(r)??new WeakMap;e.set(n,a),R.set(r,e)}return a}function K(e,t){let n=V(e),r=(z.get(n)??Promise.resolve()).then(t,t);return z.set(n,r.then(()=>void 0,()=>void 0)),r}function q(){return new Proxy({},{get(e,t){if(t!==`signer`&&t!==`then`&&typeof t!=`symbol`){if(t===`client`)throw Error(P);return t===`setSigner`?()=>{throw Error(P)}:async()=>{throw Error(P)}}}})}function Ce(e,t){return new X(e,q(),q(),M(t))}function J(e,t,n,r,i){let a=V(t);return K(a,async()=>{let t=a.signer;return t!==void 0&&t!==n||(t===n&&(a.setSigner(void 0),B.add(a)),B.has(a)&&(await r.reset(),B.delete(a)),a.signer!==void 0&&a.signer!==n)?Ce(e,i):new X(e,a,r,M(i))})}var Y=class{state;chainId;nodeUrl;blobGatewayUrl;enclaveOptions;store;enclaveProvider;constructor(e){this.state=`configuration`,this.chainId=e.chainId,this.nodeUrl=e.nodeUrl,this.blobGatewayUrl=e.blobGatewayUrl,this.enclaveOptions=e.enclaveOptions,this.store=e.store??(A()?new ve:new ye),this.enclaveProvider=e.enclaveProvider?new e.enclaveProvider({...e.enclaveOptions,store:this.store}):new k(e.enclaveOptions)}async createClient(){return X.fromConfig(this)}},X=class e{state;store;kwilClient;enclaveProvider;blobGateway;constructor(e,t,n,r){this.state=`idle`,this.store=e,this.kwilClient=t,this.enclaveProvider=n,this.blobGateway=r}static async fromConfig(t){let n=await(A()?l:c)({nodeUrl:t.nodeUrl,chainId:t.chainId});await t.enclaveProvider.load();let r=t.blobGatewayUrl??t.nodeUrl;return new e(t.store,n,t.enclaveProvider,M(r))}async addressHasProfile(e){return y(this.kwilClient,{address:e}).then(e=>{if(!e)throw Error(`has_profile returned no rows`);return e.has_profile})}async withUserSigner(e){let t=e,[n,r,i,a]=await o(this.store,this.kwilClient,t);if(a===`NEAR`){let e=t;t={signMessage:async t=>({signedMessage:await f(e,t)})}}return K(this.kwilClient,async()=>(this.kwilClient.setSigner(n),new Z(this,t,n,r,i,a,xe(this,n))))}async logOut(){return this}},Z=class{state;store;#e;#t;signer;kwilSigner;walletIdentifier;walletPublicKey;walletType;blobGateway;constructor(e,t,n,r,i,a,o){this.state=`with-user-signer`,this.store=e.store,this.#e=e.kwilClient,this.#t=e.enclaveProvider,this.signer=t,this.kwilSigner=n,this.walletIdentifier=r,this.walletPublicKey=i,this.walletType=a,this.blobGateway=o,this.#t.setSigner(this.signer)}get kwilClient(){return U(this.#e,this.kwilSigner)}get enclaveProvider(){return G(this.#t,this.#e,this.kwilSigner)}async logOut(){return J(this.store,this.#e,this.kwilSigner,this.#t,this.blobGateway.url)}async hasProfile(){let e=this.walletIdentifier;if(this.walletType===`NEAR`){if(!this.walletPublicKey)throw Error(`NEAR wallet public key is required`);e=this.walletPublicKey}return y(this.kwilClient,{address:e}).then(e=>{if(!e)throw Error(`has_profile returned no rows`);return e.has_profile})}async createUserEncryptionProfile(e,t){return await K(this.#e,async()=>{H(this.#e,this.kwilSigner),await this.enclaveProvider.reconfigure({mode:`new`,userId:e,walletAddress:this.walletIdentifier,walletPublicKey:this.walletPublicKey,walletType:this.walletType,encryptionPasswordStore:t,expectedUserEncryptionPublicKey:void 0}),H(this.#e,this.kwilSigner)}),H(this.#e,this.kwilSigner),this.enclaveProvider.ensureUserEncryptionProfile()}async logIn(){if(!await this.hasProfile())throw Error(`User does not have a profile`);let e=await le(this.kwilClient);return K(this.#e,async()=>(H(this.#e,this.kwilSigner),await this.enclaveProvider.reconfigure({mode:`existing`,userId:e.id,expectedUserEncryptionPublicKey:e.recipient_encryption_public_key,walletAddress:this.walletIdentifier,walletType:this.walletType,encryptionPasswordStore:e.encryption_password_store,walletPublicKey:this.walletPublicKey}),H(this.#e,this.kwilSigner),new $(this,e)))}};function Q(e){if(e.walletType===`NEAR`){if(!e.walletPublicKey)throw Error(`NEAR wallet public key is required`);return e.walletPublicKey}return e.walletIdentifier}var $=class{state;store;#e;#t;signer;kwilSigner;walletIdentifier;walletPublicKey;walletType;user;blobGateway;constructor(e,t){this.state=`logged-in`,this.store=e.store,this.#e=V(e.kwilClient),this.#t=W(e.enclaveProvider),this.signer=e.signer,this.kwilSigner=e.kwilSigner,this.walletIdentifier=e.walletIdentifier,this.walletPublicKey=e.walletPublicKey,this.walletType=e.walletType,this.user=t,this.blobGateway=e.blobGateway}get kwilClient(){return U(this.#e,this.kwilSigner)}get enclaveProvider(){return G(this.#t,this.#e,this.kwilSigner)}async logOut(){return J(this.store,this.#e,this.kwilSigner,this.#t,this.blobGateway.url)}async requestDWGMessage(e){return te(this.kwilClient,e).then(e=>{if(!e)throw Error(`dwg_message returned no rows`);return e.message})}async createCredential(e,r,i){let a=crypto.randomUUID(),o={...await t({publicNotes:e,plaintextContent:r,recipientEncryptionPublicKey:w(this.user.recipient_encryption_public_key),broaderMessageFor:(e,t)=>_(this.kwilClient,{public_notes_signature:e,content_uri:t,recipient_wallet:Q(this)}).then(e=>e.message),issuerSigningSecretKey:i,ukycStorageId:N(this.walletType,this.kwilSigner)}),id:a};C(o.contentUri,this.blobGateway.hasAccessToken);let s=crypto.randomUUID(),c={request_id:s,credential_id:o.id,issuer_auth_public_key:o.issuerAuthPublicKey,encryptor_public_key:o.encryptorPublicKey,content_uri:o.contentUri,content_size:o.contentSize,content_hash:E(r),public_notes:o.publicNotes,public_notes_signature:o.publicNotesSignature,broader_signature:o.broaderSignature};return await g(this.kwilClient,c),await this.#n({requestId:s,credentialIds:[o.id],original:o.encryptedContent}),n(o)}async#n(e){try{await this.blobGateway.uploadCredentialBlobs(e)}catch(t){if(!(t instanceof S))throw t;let n=await this.getCredentialById(e.credentialIds[0]).catch(()=>void 0);if(!n?.content_uri)throw t;let r=new AbortController,i=setTimeout(()=>r.abort(),6e4),a=await this.blobGateway.fetchBlob({credentialId:n.id,contentUri:n.content_uri,expectedSize:n.content_size,signal:r.signal}).catch(()=>void 0).finally(()=>clearTimeout(i)),o=e.original??e.copy;if(!a||!Se(a,o))throw t}}async removeCredential(e){let t=await this.getCredentialById(e);O(t,`"idOSCredential" with id ${e} not found`);let n=t.content_uri??null;return C(n,this.blobGateway.hasAccessToken),await b(this.kwilClient,{id:e}),n&&await this.blobGateway.deleteCredentialBlob({credentialId:e}),{id:e}}async getCredentialById(e){return ae(this.kwilClient,{id:e}).then(e=>e[0])}async shareCredential(e){return await fe(this.kwilClient,e),e}async getAllCredentials(){return se(this.kwilClient)}async getAccessGrantsOwned(){return re(this.kwilClient)}async getAttributes(){return ie(this.kwilClient)}async createAttribute(e){return await p(this.kwilClient,e),e}async getCredentialContentSha256Hash(e){let t=await this.getCredentialById(e);O(t,`"idOSCredential" with id ${e} not found`);let n=await this.#i(t);return E(n)}async getCredentialContent(e){let t=await this.getCredentialById(e);O(t,`"idOSCredential" with id ${e} not found`);let n=await this.#i(t);return D(n)}async getCredentialWithEncryptedContent(e){let t=await this.getCredentialById(e);return O(t,`"idOSCredential" with id ${e} not found`),this.#r(t)}async getCredentialSharedContent(e){let t=await this.getCredentialShared(e);O(t,`Shared credential with id ${e} not found`);let n=await this.#i(t);return D(n)}async getGrants(e){return{grants:await ce(this.kwilClient,e),totalCount:await this.getGrantsCount()}}async addWallets(e){return await ee(this.kwilClient,e),e}async getGrantsCount(){return ne(this.kwilClient,{user_id:null}).then(e=>{if(!e)throw Error(`get_access_grants_granted_count returned no rows`);return e.count})}async getCredentialShared(e){return oe(this.kwilClient,{id:e}).then(e=>e[0])}async revokeAccessGrant(e){return await de(this.kwilClient,{id:e}),{id:e}}async addWalletMessage(e){return(await h(this.kwilClient,e)).message}async addWallet(e){if(await m(this.kwilClient,e),this.user.encryption_password_store!==`mpc`)return console.log(`MPC is not enabled or the user is not using MPC`),e;if(!e.wallet_type)throw Error(`Wallet type is required for MPC users`);let t=await this.enclaveProvider.addAddressMessageToSign(e.address,e.public_key??void 0,e.wallet_type),n=await this.enclaveProvider.signTypedData(t.domain,t.types,t.value),r=await this.enclaveProvider.addAddressToMpcSecret(this.user.id,t.value,n);return r!==`success`&&console.error(`Failed to add wallet to MPC: ${r}`),e}async getWallets(){return v(this.kwilClient)}async removeWallet(e){let t=(await this.getWallets()).find(t=>t.id===e);if(!t)throw Error(`Wallet with id ${e} not found`);if(await ue(this.kwilClient,{id:e}),this.user.encryption_password_store!==`mpc`)return console.log(`MPC is not enabled or the user is not using MPC`),{id:e};let n=await this.enclaveProvider.removeAddressMessageToSign(t.address,t.public_key??void 0,t.wallet_type),r=await this.enclaveProvider.signTypedData(n.domain,n.types,n.value),i=await this.enclaveProvider.removeAddressFromMpcSecret(t.user_id,n.value,r);return i!==`success`&&console.error(`Failed to add wallet to MPC: ${i}`),{id:e}}async removeWallets(e){for(let t of e)await this.removeWallet(t);return e}async filterCredentials(e){let t=(await this.getAllCredentials()).filter(e=>!e.original_id&&!!e.public_notes).filter(t=>e.acceptedIssuers?.some(e=>e.authPublicKey===t.issuer_auth_public_key)),n=e.publicNotesFieldFilters,o=e.credentialLevelOrHigherFilter,s=e.privateFieldFilters,c=e.claimsFilter;if(c&&(t=t.filter(e=>{let t;try{t=JSON.parse(e.public_notes)}catch{throw Error(`Credential ${e.id} has non-JSON public notes.`)}return r(c,t)})),o&&(t=t.filter(e=>{let t;try{t=JSON.parse(e.public_notes)}catch{throw Error(`Credential ${e.id} has non-JSON public notes.`)}return i(o.userLevel,o.requiredAddons,t.level)})),n&&(Object.keys(n.pick).length>0||Object.keys(n.omit).length>0)&&(t=t.filter(e=>{let t;try{t=JSON.parse(e.public_notes)}catch{throw Error(`Credential ${e.id} has non-JSON public notes.`)}return a(t,n.pick,n.omit)})),s&&(Object.keys(s.pick).length>0||Object.keys(s.omit).length>0)){let e=await Promise.all(t.map(e=>this.getCredentialById(e.id)));O(e.every(e=>e!==void 0),`Some credentials could not be fetched in full form for private field filtering`);let n=await this.enclaveProvider.filterCredentials(await Promise.all(e.map(e=>this.#r(e))),s);t=t.filter(e=>n.some(t=>t.id===e.id))}return t}async requestAccessGrant(t,{consumerEncryptionPublicKey:n,consumerAuthPublicKey:r,lockedUntil:i=0}){let a=await this.getCredentialById(t);O(a,`"idOSCredential" with id ${t} not found`);let o=await this.#i(a),s=E(o);await this.enclaveProvider.ensureUserEncryptionProfile();let{content:c,encryptorPublicKey:l}=await this.enclaveProvider.encrypt(o,w(n)),u=crypto.randomUUID(),d=N(this.walletType,this.kwilSigner),f=d?ge(d,c):await he(c);C(f.uri,this.blobGateway.hasAccessToken);let p=await e(``,f.uri,(e,t)=>_(this.kwilClient,{public_notes_signature:e,content_uri:t,recipient_wallet:Q(this)}).then(e=>e.message)),m=/^[0-9a-fA-F]{64}$/.test(r)?r.toLowerCase():r,h={...p,request_id:crypto.randomUUID(),copy_id:u,original_id:a.id,content_uri:f.uri,content_size:f.size,encryptor_public_key:T(l),grantee_wallet_identifier:m,locked_until:i,content_hash:s};return await this.shareCredential(h),await this.#n({requestId:h.request_id,credentialIds:[u],copy:c}),h}async#r(e){return e.content?e:{...e,content:T(await this.#a(e)),content_uri:null,content_size:null}}async#i(e){return await this.enclaveProvider.ensureUserEncryptionProfile(),this.enclaveProvider.decrypt(await this.#a(e),w(e.encryptor_public_key))}async#a(e){return _e(e,this.blobGateway)}};function we(e){return new Y({nodeUrl:e.nodeUrl,blobGatewayUrl:e.blobGatewayUrl,enclaveOptions:e.enclaveOptions})}export{k as IframeEnclave,we as createIDOSClient,Y as idOSClientConfiguration,X as idOSClientIdle,$ as idOSClientLoggedIn,Z as idOSClientWithUserSigner,f as signNearMessage,pe as toDelegatedWriteGrantBaseParams};
1
+ import{buildEphemeralSignedCredentialContentReference as e,buildPreliminaryIDOSCredential as t,mapPreliminaryToIDOSCredential as n,matchClaims as r,matchLevelOrHigher as i,recordFilter as a}from"@idos-network/credentials/utils";import{createClientKwilSigner as o,createKgwAuthenticatedBlobGateway as s,createNodeKwilClient as c,createWebKwilClient as l,signNearMessage as u}from"@idos-network/kwil-infra";import{addAttribute as d,addWallet as f,addWalletMessage as p,addWallets as m,createPreliminaryCredential as h,credentialBroaderMessage as g,dwgMessage as _,getAccessGrantsGrantedCount as ee,getAccessGrantsOwned as te,getAttributes as ne,getCredentialOwned as re,getCredentialShared as ie,getCredentials as ae,getGrants as oe,getUser as se,getWallets as v,hasProfile as y,removeCredential as b,removeWallet as ce,revokeAccessGrant as le,sharePreliminaryCredential as ue,toDelegatedWriteGrantBaseParams as de}from"@idos-network/kwil-infra/actions";import{NodeKwil as fe}from"@idos-network/kwil-js";import{BlobGateway as x,BlobGatewayUploadOutcomeUnknownError as pe,createBlobContentReference as me,isUkycContentUri as he,resolveCredentialEncryptedContent as ge}from"@idos-network/utils/blob-gateway";import{base64Decode as S,base64Encode as C,hexEncodeSha256Hash as w,utf8Decode as T}from"@idos-network/utils/codecs";import{LocalStorageStore as _e,MemoryStore as ve}from"@idos-network/utils/store";import E from"tiny-invariant";import{BaseProvider as D}from"@idos-network/enclave";var O=class extends D{container;iframe;hostUrl;bound=!1;constructor(e){if(super(e),!this.options.container)throw Error(`container is required`);this.container=this.options.container,this.hostUrl=new URL(this.options.url??`https://enclave.idos.network`),this.iframe=document.createElement(`iframe`),this.iframe.id=`idos-enclave-iframe`}async load(){await this.createAndLoadIframe(),await this.requestToEnclave(`load`),await this.reconfigure(),await this.bindMessageListener()}async reset(){throw Error(`Embedding pages cannot reset enclave storage`)}async reconfigure(e={}){super.reconfigure(e),await this.requestToEnclave(`reconfigure`,this.options)}async confirm(e){this.showEnclave();try{return await this.requestToEnclave(`confirm`,e)}catch(e){return console.error(e),!1}finally{this.hideEnclave()}}async filterCredentials(e,t){return await this.requestToEnclave(`filterCredentials`,e,t)}async encrypt(e,t){return this.requestToEnclave(`encrypt`,e,t)}async decrypt(e,t){return this.requestToEnclave(`decrypt`,e,t)}async backupUserEncryptionProfile(){this.showEnclave();try{await this.requestToEnclave(`backupUserEncryptionProfile`)}catch(e){console.error(e)}finally{this.hideEnclave()}}async ensureUserEncryptionProfile(){this.showEnclave();try{return await this.requestToEnclave(`ensureUserEncryptionProfile`)}finally{this.hideEnclave()}}async addAddressMessageToSign(e,t,n){return this.requestToEnclave(`addAddressMessageToSign`,e,t,n)}async removeAddressMessageToSign(e,t,n){return this.requestToEnclave(`removeAddressMessageToSign`,e,t,n)}async addAddressToMpcSecret(e,t,n){return this.requestToEnclave(`addAddressToMpcSecret`,e,t,n)}async removeAddressFromMpcSecret(e,t,n){return this.requestToEnclave(`removeAddressFromMpcSecret`,e,t,n)}async createAndLoadIframe(){let e=document.querySelector(this.container);if(!e)throw Error(`Can't find container with selector ${this.container}`);let t=[`publickey-credentials-get`,`storage-access`],n=[`forms`,`modals`,`popups`,`popups-to-escape-sandbox`,`same-origin`,`scripts`].map(e=>`allow-${e}`),r={"aspect-ratio":`4/1`,"background-color":`transparent`,border:`none`,display:`block`,overflow:`hidden`,width:`100%`};this.iframe.allow=t.join(`; `),this.iframe.referrerPolicy=`origin`,this.iframe.sandbox.add(...n),this.iframe.src=this.hostUrl.toString();for(let[e,t]of Object.entries(r))this.iframe.style.setProperty(e,t);let i;for(;i=document.getElementById(this.iframe.id);)console.log(`reinstalling idOS iframe...`),e.removeChild(i);return e.appendChild(this.iframe),new Promise(e=>this.iframe.addEventListener(`load`,()=>{e()},{once:!0}))}showEnclave(){this.iframe.parentElement.classList.add(`visible`)}hideEnclave(){this.iframe.parentElement.classList.remove(`visible`)}async requestToEnclave(e,...t){return new Promise((n,r)=>{let{port1:i,port2:a}=new MessageChannel;i.onmessage=({data:e})=>{i.close(),e.error?r(e.error):n(e.result)},this.iframe.contentWindow.postMessage({method:e,data:t},this.hostUrl.origin,[a])})}bindMessageListener(){this.bound||window.addEventListener(`message`,this.onMessage.bind(this)),this.bound=!0}async onMessage(e){if(!e||!e.data||typeof e.data!=`object`||e.data.type!==`idOS:signTypedData`||e.origin!==this.hostUrl.origin)return;let t=e.data.payload,n=await this.signTypedData(t.domain,t.types,t.value);await this.requestToEnclave(`signTypedDataResponse`,n)}};function k(){return typeof window<`u`}function A(e){return e.client instanceof fe}function j(e){return k()?new x({url:e,fetchFn:(e,t)=>fetch(e,{...t,credentials:`include`})}):new x({url:e})}function M(e,t){return A(e.kwilClient)?s({url:e.blobGateway.url,kwilClient:e.kwilClient,signer:t}):e.blobGateway}function N(e,t){return e.byteLength===t.byteLength&&e.every((e,n)=>e===t[n])}const P="This idOS client is stale: another signer was set or it was logged out. Use the client returned by the latest `withUserSigner()`.",F=new WeakMap,I=new WeakMap,L=new WeakMap,R=new WeakMap,z=new WeakMap,B=new WeakSet;function V(e){return F.get(e)??e}function H(e,t){if(e.signer!==t)throw Error(P)}function U(e,t){let n=V(e),r=t?I.get(n)?.get(t):void 0;if(r)return r;let i=()=>H(n,t),a={get signer(){return i(),n.signer},get client(){return i(),n.client},call:async(...e)=>(i(),n.call(...e)),execute:async(...e)=>(i(),n.execute(...e)),waitForTx:async e=>(i(),n.waitForTx(e)),setSigner:e=>{i(),n.setSigner(e)}};if(F.set(a,n),t){let e=I.get(n)??new WeakMap;e.set(t,a),I.set(n,e)}return a}function W(e){return e&&L.get(e)||e}function G(e,t,n){let r=W(e),i=n?R.get(r)?.get(n):void 0;if(i)return i;let a=new Proxy(r,{get(e,r){if(r===`then`||typeof r==`symbol`)return;let i=Reflect.get(e,r,e);return typeof i==`function`?(...r)=>(H(t,n),i.apply(e,r)):(H(t,n),i)}});if(L.set(a,r),n){let e=R.get(r)??new WeakMap;e.set(n,a),R.set(r,e)}return a}function K(e,t){let n=V(e),r=(z.get(n)??Promise.resolve()).then(t,t);return z.set(n,r.then(()=>void 0,()=>void 0)),r}function q(){return new Proxy({},{get(e,t){if(t!==`signer`&&t!==`then`&&typeof t!=`symbol`){if(t===`client`)throw Error(P);return t===`setSigner`?()=>{throw Error(P)}:async()=>{throw Error(P)}}}})}function ye(e,t){return new X(e,q(),q(),j(t))}function J(e,t,n,r,i){let a=V(t);return K(a,async()=>{let t=a.signer;return t!==void 0&&t!==n||(t===n&&(a.setSigner(void 0),B.add(a)),B.has(a)&&(await r.reset(),B.delete(a)),a.signer!==void 0&&a.signer!==n)?ye(e,i):new X(e,a,r,j(i))})}var Y=class{state;chainId;nodeUrl;blobGatewayUrl;enclaveOptions;store;enclaveProvider;constructor(e){this.state=`configuration`,this.chainId=e.chainId,this.nodeUrl=e.nodeUrl,this.blobGatewayUrl=e.blobGatewayUrl,this.enclaveOptions=e.enclaveOptions,this.store=e.store??(k()?new _e:new ve),this.enclaveProvider=e.enclaveProvider?new e.enclaveProvider({...e.enclaveOptions,store:this.store}):new O(e.enclaveOptions)}async createClient(){return X.fromConfig(this)}},X=class e{state;store;kwilClient;enclaveProvider;blobGateway;constructor(e,t,n,r){this.state=`idle`,this.store=e,this.kwilClient=t,this.enclaveProvider=n,this.blobGateway=r}static async fromConfig(t){let n=await(k()?l:c)({nodeUrl:t.nodeUrl,chainId:t.chainId});await t.enclaveProvider.load();let r=t.blobGatewayUrl??t.nodeUrl;return new e(t.store,n,t.enclaveProvider,j(r))}async addressHasProfile(e){return y(this.kwilClient,{address:e}).then(e=>{if(!e)throw Error(`has_profile returned no rows`);return e.has_profile})}async withUserSigner(e){let t=e,[n,r,i,a]=await o(this.store,this.kwilClient,t);if(a===`NEAR`){let e=t;t={signMessage:async t=>({signedMessage:await u(e,t)})}}return K(this.kwilClient,async()=>(this.kwilClient.setSigner(n),new Z(this,t,n,r,i,a,M(this,n))))}async logOut(){return this}},Z=class{state;store;#e;#t;signer;kwilSigner;walletIdentifier;walletPublicKey;walletType;blobGateway;constructor(e,t,n,r,i,a,o){this.state=`with-user-signer`,this.store=e.store,this.#e=e.kwilClient,this.#t=e.enclaveProvider,this.signer=t,this.kwilSigner=n,this.walletIdentifier=r,this.walletPublicKey=i,this.walletType=a,this.blobGateway=o,this.#t.setSigner(this.signer)}get kwilClient(){return U(this.#e,this.kwilSigner)}get enclaveProvider(){return G(this.#t,this.#e,this.kwilSigner)}async logOut(){return J(this.store,this.#e,this.kwilSigner,this.#t,this.blobGateway.url)}async hasProfile(){let e=this.walletIdentifier;if(this.walletType===`NEAR`){if(!this.walletPublicKey)throw Error(`NEAR wallet public key is required`);e=this.walletPublicKey}return y(this.kwilClient,{address:e}).then(e=>{if(!e)throw Error(`has_profile returned no rows`);return e.has_profile})}async createUserEncryptionProfile(e,t){return await K(this.#e,async()=>{H(this.#e,this.kwilSigner),await this.enclaveProvider.reconfigure({mode:`new`,userId:e,walletAddress:this.walletIdentifier,walletPublicKey:this.walletPublicKey,walletType:this.walletType,encryptionPasswordStore:t,expectedUserEncryptionPublicKey:void 0}),H(this.#e,this.kwilSigner)}),H(this.#e,this.kwilSigner),this.enclaveProvider.ensureUserEncryptionProfile()}async logIn(){if(!await this.hasProfile())throw Error(`User does not have a profile`);let e=await se(this.kwilClient);return K(this.#e,async()=>(H(this.#e,this.kwilSigner),await this.enclaveProvider.reconfigure({mode:`existing`,userId:e.id,expectedUserEncryptionPublicKey:e.recipient_encryption_public_key,walletAddress:this.walletIdentifier,walletType:this.walletType,encryptionPasswordStore:e.encryption_password_store,walletPublicKey:this.walletPublicKey}),H(this.#e,this.kwilSigner),new $(this,e)))}};function Q(e){if(e.walletType===`NEAR`){if(!e.walletPublicKey)throw Error(`NEAR wallet public key is required`);return e.walletPublicKey}return e.walletIdentifier}var $=class{state;store;#e;#t;signer;kwilSigner;walletIdentifier;walletPublicKey;walletType;user;blobGateway;constructor(e,t){this.state=`logged-in`,this.store=e.store,this.#e=V(e.kwilClient),this.#t=W(e.enclaveProvider),this.signer=e.signer,this.kwilSigner=e.kwilSigner,this.walletIdentifier=e.walletIdentifier,this.walletPublicKey=e.walletPublicKey,this.walletType=e.walletType,this.user=t,this.blobGateway=e.blobGateway}get kwilClient(){return U(this.#e,this.kwilSigner)}get enclaveProvider(){return G(this.#t,this.#e,this.kwilSigner)}async logOut(){return J(this.store,this.#e,this.kwilSigner,this.#t,this.blobGateway.url)}async requestDWGMessage(e){return _(this.kwilClient,e).then(e=>{if(!e)throw Error(`dwg_message returned no rows`);return e.message})}async createCredential(e,r,i){let a=crypto.randomUUID(),o={...await t({publicNotes:e,plaintextContent:r,recipientEncryptionPublicKey:S(this.user.recipient_encryption_public_key),broaderMessageFor:(e,t)=>g(this.kwilClient,{public_notes_signature:e,content_uri:t,recipient_wallet:Q(this)}).then(e=>e.message),issuerSigningSecretKey:i}),id:a},s=crypto.randomUUID(),c={request_id:s,credential_id:o.id,issuer_auth_public_key:o.issuerAuthPublicKey,encryptor_public_key:o.encryptorPublicKey,content_uri:o.contentUri,content_size:o.contentSize,content_hash:w(r),public_notes:o.publicNotes,public_notes_signature:o.publicNotesSignature,broader_signature:o.broaderSignature};return await h(this.kwilClient,c),await this.#n({requestId:s,credentialIds:[o.id],original:o.encryptedContent}),n(o)}async#n(e){try{await this.blobGateway.uploadCredentialBlobs(e)}catch(t){if(!(t instanceof pe))throw t;let n=await this.getCredentialById(e.credentialIds[0]).catch(()=>void 0);if(!n?.content_uri)throw t;let r=new AbortController,i=setTimeout(()=>r.abort(),6e4),a=await this.blobGateway.fetchBlob({credentialId:n.id,contentUri:n.content_uri,expectedSize:n.content_size,signal:r.signal}).catch(()=>void 0).finally(()=>clearTimeout(i)),o=e.original??e.copy;if(!a||!N(a,o))throw t}}async removeCredential(e){let t=await this.getCredentialById(e);E(t,`"idOSCredential" with id ${e} not found`);let n=t.content_uri??null;if(he(n))throw Error(`ukyc:// credentials can only be removed by their MM operator's data wipe`);return await b(this.kwilClient,{id:e}),n&&await this.blobGateway.deleteCredentialBlob({credentialId:e}),{id:e}}async getCredentialById(e){return re(this.kwilClient,{id:e}).then(e=>e[0])}async shareCredential(e){return await ue(this.kwilClient,e),e}async getAllCredentials(){return ae(this.kwilClient)}async getAccessGrantsOwned(){return te(this.kwilClient)}async getAttributes(){return ne(this.kwilClient)}async createAttribute(e){return await d(this.kwilClient,e),e}async getCredentialContentSha256Hash(e){let t=await this.getCredentialById(e);E(t,`"idOSCredential" with id ${e} not found`);let n=await this.#i(t);return w(n)}async getCredentialContent(e){let t=await this.getCredentialById(e);E(t,`"idOSCredential" with id ${e} not found`);let n=await this.#i(t);return T(n)}async getCredentialWithEncryptedContent(e){let t=await this.getCredentialById(e);return E(t,`"idOSCredential" with id ${e} not found`),this.#r(t)}async getCredentialSharedContent(e){let t=await this.getCredentialShared(e);E(t,`Shared credential with id ${e} not found`);let n=await this.#i(t);return T(n)}async getGrants(e){return{grants:await oe(this.kwilClient,e),totalCount:await this.getGrantsCount()}}async addWallets(e){return await m(this.kwilClient,e),e}async getGrantsCount(){return ee(this.kwilClient,{user_id:null}).then(e=>{if(!e)throw Error(`get_access_grants_granted_count returned no rows`);return e.count})}async getCredentialShared(e){return ie(this.kwilClient,{id:e}).then(e=>e[0])}async revokeAccessGrant(e){return await le(this.kwilClient,{id:e}),{id:e}}async addWalletMessage(e){return(await p(this.kwilClient,e)).message}async addWallet(e){if(await f(this.kwilClient,e),this.user.encryption_password_store!==`mpc`)return console.log(`MPC is not enabled or the user is not using MPC`),e;if(!e.wallet_type)throw Error(`Wallet type is required for MPC users`);let t=await this.enclaveProvider.addAddressMessageToSign(e.address,e.public_key??void 0,e.wallet_type),n=await this.enclaveProvider.signTypedData(t.domain,t.types,t.value),r=await this.enclaveProvider.addAddressToMpcSecret(this.user.id,t.value,n);return r!==`success`&&console.error(`Failed to add wallet to MPC: ${r}`),e}async getWallets(){return v(this.kwilClient)}async removeWallet(e){let t=(await this.getWallets()).find(t=>t.id===e);if(!t)throw Error(`Wallet with id ${e} not found`);if(await ce(this.kwilClient,{id:e}),this.user.encryption_password_store!==`mpc`)return console.log(`MPC is not enabled or the user is not using MPC`),{id:e};let n=await this.enclaveProvider.removeAddressMessageToSign(t.address,t.public_key??void 0,t.wallet_type),r=await this.enclaveProvider.signTypedData(n.domain,n.types,n.value),i=await this.enclaveProvider.removeAddressFromMpcSecret(t.user_id,n.value,r);return i!==`success`&&console.error(`Failed to add wallet to MPC: ${i}`),{id:e}}async removeWallets(e){for(let t of e)await this.removeWallet(t);return e}async filterCredentials(e){let t=(await this.getAllCredentials()).filter(e=>!e.original_id&&!!e.public_notes).filter(t=>e.acceptedIssuers?.some(e=>e.authPublicKey===t.issuer_auth_public_key)),n=e.publicNotesFieldFilters,o=e.credentialLevelOrHigherFilter,s=e.privateFieldFilters,c=e.claimsFilter;if(c&&(t=t.filter(e=>{let t;try{t=JSON.parse(e.public_notes)}catch{throw Error(`Credential ${e.id} has non-JSON public notes.`)}return r(c,t)})),o&&(t=t.filter(e=>{let t;try{t=JSON.parse(e.public_notes)}catch{throw Error(`Credential ${e.id} has non-JSON public notes.`)}return i(o.userLevel,o.requiredAddons,t.level)})),n&&(Object.keys(n.pick).length>0||Object.keys(n.omit).length>0)&&(t=t.filter(e=>{let t;try{t=JSON.parse(e.public_notes)}catch{throw Error(`Credential ${e.id} has non-JSON public notes.`)}return a(t,n.pick,n.omit)})),s&&(Object.keys(s.pick).length>0||Object.keys(s.omit).length>0)){let e=await Promise.all(t.map(e=>this.getCredentialById(e.id)));E(e.every(e=>e!==void 0),`Some credentials could not be fetched in full form for private field filtering`);let n=await this.enclaveProvider.filterCredentials(await Promise.all(e.map(e=>this.#r(e))),s);t=t.filter(e=>n.some(t=>t.id===e.id))}return t}async requestAccessGrant(t,{consumerEncryptionPublicKey:n,consumerAuthPublicKey:r,lockedUntil:i=0}){let a=await this.getCredentialById(t);E(a,`"idOSCredential" with id ${t} not found`);let o=await this.#i(a),s=w(o);await this.enclaveProvider.ensureUserEncryptionProfile();let{content:c,encryptorPublicKey:l}=await this.enclaveProvider.encrypt(o,S(n)),u=crypto.randomUUID(),d=await me(c),f=await e(``,d.uri,(e,t)=>g(this.kwilClient,{public_notes_signature:e,content_uri:t,recipient_wallet:Q(this)}).then(e=>e.message)),p=/^[0-9a-fA-F]{64}$/.test(r)?r.toLowerCase():r,m={...f,request_id:crypto.randomUUID(),copy_id:u,original_id:a.id,content_uri:d.uri,content_size:d.size,encryptor_public_key:C(l),grantee_wallet_identifier:p,locked_until:i,content_hash:s};return await this.shareCredential(m),await this.#n({requestId:m.request_id,credentialIds:[u],copy:c}),m}async#r(e){return e.content?e:{...e,content:C(await this.#a(e)),content_uri:null,content_size:null}}async#i(e){return await this.enclaveProvider.ensureUserEncryptionProfile(),this.enclaveProvider.decrypt(await this.#a(e),S(e.encryptor_public_key))}async#a(e){return ge(e,this.blobGateway)}};function be(e){return new Y({nodeUrl:e.nodeUrl,blobGatewayUrl:e.blobGatewayUrl,enclaveOptions:e.enclaveOptions})}export{O as IframeEnclave,be as createIDOSClient,Y as idOSClientConfiguration,X as idOSClientIdle,$ as idOSClientLoggedIn,Z as idOSClientWithUserSigner,u as signNearMessage,de as toDelegatedWriteGrantBaseParams};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["createAttribute","requestAddWalletMessage"],"sources":["../src/enclave/iframe-enclave.ts","../src/index.ts"],"sourcesContent":["import type { idOSCredentialRecord as idOSCredential } from \"@idos-network/credentials/types\";\nimport type {\n AddAddressMessageToSign,\n AddAddressSignatureMessage,\n RemoveAddressMessageToSign,\n RemoveAddressSignatureMessage,\n} from \"@idos-network/enclave/mpc\";\n\nimport {\n BaseProvider,\n type EnclaveOptions,\n type PublicEncryptionProfile,\n} from \"@idos-network/enclave\";\n\nimport type { BaseProviderMethodArgs, BaseProviderMethodReturn } from \"./helpers\";\n\nexport interface IframeEnclaveOptions extends EnclaveOptions {\n container: string;\n url?: string;\n throwOnUserCancelUnlock?: boolean;\n}\n\nexport class IframeEnclave extends BaseProvider<IframeEnclaveOptions> {\n private container: string;\n private iframe: HTMLIFrameElement;\n private hostUrl: URL;\n private bound = false;\n\n constructor(options: IframeEnclaveOptions) {\n super(options);\n\n if (!this.options.container) {\n throw new Error(\"container is required\");\n }\n\n this.container = this.options.container;\n this.hostUrl = new URL(this.options.url ?? \"https://enclave.idos.network\");\n this.iframe = document.createElement(\"iframe\");\n this.iframe.id = \"idos-enclave-iframe\";\n }\n\n /** @see parent method */\n async load(): Promise<void> {\n // First we have to create and load the iframe\n await this.createAndLoadIframe();\n\n // Load the enclave from the store (trigger load() method in the iframe)\n await this.requestToEnclave(\"load\");\n\n // Pass current options\n await this.reconfigure();\n\n // Bind the message listener to the iframe (in case iframe -> enclave comm)\n await this.bindMessageListener();\n }\n\n /**\n * Embedding pages cannot reset enclave storage. The iframe rejects `reset`\n * because it deletes every idOS-* key with no origin check.\n */\n async reset(): Promise<void> {\n throw new Error(\"Embedding pages cannot reset enclave storage\");\n }\n\n /** @override parent method to call iframe */\n async reconfigure(options: Omit<IframeEnclaveOptions, \"container\" | \"url\"> = {}): Promise<void> {\n super.reconfigure(options);\n await this.requestToEnclave(\"reconfigure\", this.options);\n }\n\n /** @override parent method to call iframe */\n async confirm(message: string): Promise<boolean> {\n this.showEnclave();\n\n try {\n return await this.requestToEnclave(\"confirm\", message);\n } catch (error) {\n console.error(error);\n return false;\n } finally {\n this.hideEnclave();\n }\n }\n\n /** @override parent method to call iframe */\n async filterCredentials(\n credentials: idOSCredential[],\n privateFieldFilters: { pick: Record<string, unknown[]>; omit: Record<string, unknown[]> },\n ): Promise<idOSCredential[]> {\n return await this.requestToEnclave(\"filterCredentials\", credentials, privateFieldFilters);\n }\n\n /** @override parent method to call iframe */\n async encrypt(\n message: Uint8Array,\n receiverPublicKey: Uint8Array,\n ): Promise<{ content: Uint8Array; encryptorPublicKey: Uint8Array }> {\n return this.requestToEnclave(\"encrypt\", message, receiverPublicKey);\n }\n\n /** @override parent method to call iframe */\n async decrypt(\n message: Uint8Array,\n senderPublicKey: Uint8Array,\n ): Promise<Uint8Array<ArrayBufferLike>> {\n return this.requestToEnclave(\"decrypt\", message, senderPublicKey);\n }\n\n /** @override parent method to call iframe */\n async backupUserEncryptionProfile(): Promise<void> {\n this.showEnclave();\n\n try {\n await this.requestToEnclave(\"backupUserEncryptionProfile\");\n } catch (error) {\n console.error(error);\n } finally {\n this.hideEnclave();\n }\n }\n\n /** @override parent method to call iframe */\n async ensureUserEncryptionProfile(): Promise<PublicEncryptionProfile> {\n this.showEnclave();\n\n try {\n return await this.requestToEnclave(\"ensureUserEncryptionProfile\");\n } finally {\n this.hideEnclave();\n }\n }\n\n async addAddressMessageToSign(\n address: string,\n publicKey: string | undefined,\n addressToAddType: string,\n ): Promise<AddAddressMessageToSign> {\n return this.requestToEnclave(\"addAddressMessageToSign\", address, publicKey, addressToAddType);\n }\n\n async removeAddressMessageToSign(\n address: string,\n publicKey: string | undefined,\n addressToRemoveType: string,\n ): Promise<RemoveAddressMessageToSign> {\n return this.requestToEnclave(\n \"removeAddressMessageToSign\",\n address,\n publicKey,\n addressToRemoveType,\n );\n }\n\n async addAddressToMpcSecret(\n userId: string,\n message: AddAddressSignatureMessage,\n signature: string,\n ): Promise<string> {\n return this.requestToEnclave(\"addAddressToMpcSecret\", userId, message, signature);\n }\n\n async removeAddressFromMpcSecret(\n userId: string,\n message: RemoveAddressSignatureMessage,\n signature: string,\n ): Promise<string> {\n return this.requestToEnclave(\"removeAddressFromMpcSecret\", userId, message, signature);\n }\n\n private async createAndLoadIframe(): Promise<void> {\n const container = document.querySelector(this.container);\n\n if (!container) {\n throw new Error(`Can't find container with selector ${this.container}`);\n }\n\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy#directives\n const permissionsPolicies = [\"publickey-credentials-get\", \"storage-access\"];\n\n // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#sandbox\n const liftedSandboxRestrictions = [\n \"forms\",\n \"modals\",\n \"popups\",\n \"popups-to-escape-sandbox\",\n \"same-origin\",\n \"scripts\",\n ].map((toLift) => `allow-${toLift}`);\n\n // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#referrerpolicy\n const referrerPolicy = \"origin\";\n\n const styles = {\n \"aspect-ratio\": \"4/1\",\n \"background-color\": \"transparent\",\n border: \"none\",\n display: \"block\",\n overflow: \"hidden\",\n width: \"100%\",\n };\n\n this.iframe.allow = permissionsPolicies.join(\"; \");\n this.iframe.referrerPolicy = referrerPolicy;\n this.iframe.sandbox.add(...liftedSandboxRestrictions);\n this.iframe.src = this.hostUrl.toString();\n for (const [k, v] of Object.entries(styles)) {\n this.iframe.style.setProperty(k, v);\n }\n\n let el: HTMLElement | null;\n // oxlint-disable-next-line no-cond-assign -- it's on purpose\n while ((el = document.getElementById(this.iframe.id))) {\n console.log(\"reinstalling idOS iframe...\");\n container.removeChild(el);\n }\n container.appendChild(this.iframe);\n\n return new Promise((resolve) =>\n this.iframe.addEventListener(\n \"load\",\n () => {\n resolve();\n },\n { once: true },\n ),\n );\n }\n\n private showEnclave(): void {\n // oxlint-disable-next-line typescript/no-non-null-assertion -- Make the explosion visible.\n this.iframe.parentElement!.classList.add(\"visible\");\n }\n\n private hideEnclave(): void {\n // oxlint-disable-next-line typescript/no-non-null-assertion -- Make the explosion visible.\n this.iframe.parentElement!.classList.remove(\"visible\");\n }\n\n private async requestToEnclave<TMethod extends keyof BaseProviderMethodArgs>(\n method: TMethod,\n ...args: BaseProviderMethodArgs[TMethod]\n ): Promise<BaseProviderMethodReturn[TMethod]> {\n return new Promise((resolve, reject) => {\n const { port1, port2 } = new MessageChannel();\n\n port1.onmessage = ({ data }) => {\n port1.close();\n // oxlint-disable-next-line no-unused-expressions\n data.error ? reject(data.error) : resolve(data.result);\n };\n\n // oxlint-disable-next-line typescript/no-non-null-assertion -- Make the explosion visible.\n this.iframe.contentWindow!.postMessage(\n {\n method,\n data: args,\n },\n this.hostUrl.origin,\n [port2],\n );\n });\n }\n\n private bindMessageListener(): void {\n if (!this.bound) window.addEventListener(\"message\", this.onMessage.bind(this));\n this.bound = true;\n }\n\n private async onMessage(message: MessageEvent): Promise<void> {\n // We can't be sure about the message and the content\n // so we have to validate it carefully.\n if (!message || !message.data || typeof message.data !== \"object\") return;\n\n if (message.data.type !== \"idOS:signTypedData\" || message.origin !== this.hostUrl.origin)\n return;\n\n const payload = message.data.payload;\n const signature = await this.signTypedData(payload.domain, payload.types, payload.value);\n await this.requestToEnclave(\"signTypedDataResponse\", signature);\n }\n}\n","import type {\n BaseProvider,\n EncryptionPasswordStore,\n PublicEncryptionProfile,\n} from \"@idos-network/enclave\";\n\nimport {\n buildEphemeralSignedCredentialContentReference,\n buildPreliminaryIDOSCredential,\n mapPreliminaryToIDOSCredential,\n matchClaims,\n matchLevelOrHigher,\n type PreliminaryIDOSCredential,\n recordFilter,\n type BaseLevel,\n type Addon,\n type Claim,\n type ClaimRequirements,\n type Claims,\n type ClaimSource,\n type ClaimSources,\n} from \"@idos-network/credentials/utils\";\nimport {\n createClientKwilSigner,\n createKgwAuthenticatedBlobGateway,\n createNodeKwilClient,\n createWebKwilClient,\n isMmTokenAuth,\n type KwilActionClient,\n mmTokenStorageId,\n signNearMessage,\n type Wallet,\n} from \"@idos-network/kwil-infra\";\nimport {\n type AddAttributeInput,\n type AddWalletInput,\n type AddWalletMessageInput,\n addWallet,\n addWalletMessage as requestAddWalletMessage,\n addWallets,\n addAttribute as createAttribute,\n createPreliminaryCredential,\n credentialBroaderMessage,\n type CreatePreliminaryCredentialInput,\n dwgMessage,\n type GetAccessGrantsGrantedInput,\n type GetWalletsOutput,\n getAccessGrantsGrantedCount,\n getAccessGrantsOwned,\n getAttributes,\n getCredentialOwned,\n getCredentialShared,\n getCredentials,\n getGrants,\n getUser,\n getWallets,\n hasProfile,\n type idOSCredential,\n type idOSCredentialListItem,\n type idOSDelegatedWriteGrant,\n type DelegatedWriteGrantBaseParams,\n toDelegatedWriteGrantBaseParams,\n type idOSGrant,\n type idOSUser,\n type idOSUserAttribute,\n type idOSWallet,\n removeCredential,\n removeWallet,\n revokeAccessGrant,\n type SharePreliminaryCredentialInput,\n sharePreliminaryCredential,\n type WalletType,\n} from \"@idos-network/kwil-infra/actions\";\nimport { NodeKwil, type KwilSigner } from \"@idos-network/kwil-js\";\nimport {\n BlobGateway,\n BlobGatewayUploadOutcomeUnknownError,\n createBlobContentReference,\n createUkycContentReference,\n requireAccessTokenForUkycContent,\n resolveCredentialEncryptedContent,\n type UploadCredentialBlobsParams,\n} from \"@idos-network/utils/blob-gateway\";\nimport {\n base64Decode,\n base64Encode,\n hexEncodeSha256Hash,\n utf8Decode,\n} from \"@idos-network/utils/codecs\";\nimport { LocalStorageStore, MemoryStore, type Store } from \"@idos-network/utils/store\";\nimport invariant from \"tiny-invariant\";\n\nimport { IframeEnclave } from \"./enclave/iframe-enclave\";\nexport { IframeEnclave };\n\ntype Properties<T> = {\n // oxlint-disable-next-line typescript/no-restricted-types -- All functions are to be removed.\n [K in keyof T as Exclude<T[K], Function> extends never ? never : K]: T[K];\n};\n\nfunction isBrowserRuntime(): boolean {\n return typeof window !== \"undefined\";\n}\n\nfunction usesNodeKwil(kwilClient: KwilActionClient): boolean {\n return kwilClient.client instanceof NodeKwil;\n}\n\nfunction idleBlobGateway(url: string): BlobGateway {\n if (!isBrowserRuntime()) {\n return new BlobGateway({ url });\n }\n\n return new BlobGateway({\n url,\n // Browser blob reads need the KGW HttpOnly session cookie. That only works if the\n // blob gateway is covered by the cookie's Domain (typically same host as nodeUrl/KGW).\n fetchFn: (input, init) => fetch(input, { ...init, credentials: \"include\" }),\n });\n}\n\nfunction blobGatewayForSigner(idle: idOSClientIdle, kwilSigner: KwilSigner): BlobGateway {\n if (usesNodeKwil(idle.kwilClient)) {\n return createKgwAuthenticatedBlobGateway({\n url: idle.blobGateway.url,\n kwilClient: idle.kwilClient,\n signer: kwilSigner,\n });\n }\n\n return isMmTokenAuth(kwilSigner)\n ? idle.blobGateway.withAccessToken(kwilSigner.accessToken)\n : idle.blobGateway;\n}\n\nfunction ukycStorageIdForWallet(\n walletType: WalletType,\n kwilSigner: KwilSigner,\n): string | undefined {\n if (walletType !== \"MM\") {\n return undefined;\n }\n return mmTokenStorageId(kwilSigner);\n}\n\n// Deadline for reading a blob back after an unknown upload outcome. A slower read leaves the\n// outcome unknown, which callers already have to handle, instead of hanging the call.\nconst READ_BACK_TIMEOUT_MS = 60_000;\n\nfunction bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n return a.byteLength === b.byteLength && a.every((byte, index) => byte === b[index]);\n}\n\nconst STALE_CLIENT =\n \"This idOS client is stale: another signer was set or it was logged out. Use the client returned by the latest `withUserSigner()`.\";\n\n// Wrappers from one idle client share its Kwil client and enclave. `rawOf` unwraps the\n// guard below; `turns` keeps signer replacement and enclave reconfiguration from interleaving.\nconst rawOf = new WeakMap<KwilActionClient, KwilActionClient>();\nconst boundOf = new WeakMap<KwilActionClient, WeakMap<KwilSigner, KwilActionClient>>();\nconst rawEnclaveOf = new WeakMap<BaseProvider, BaseProvider>();\nconst boundEnclaveOf = new WeakMap<BaseProvider, WeakMap<KwilSigner, BaseProvider>>();\nconst turns = new WeakMap<KwilActionClient, Promise<void>>();\nconst resetPending = new WeakSet<KwilActionClient>();\n\nfunction sharedKwilClient(kwilClient: KwilActionClient): KwilActionClient {\n return rawOf.get(kwilClient) ?? kwilClient;\n}\n\nfunction assertSigner(kwilClient: KwilActionClient, kwilSigner: KwilSigner): void {\n if (kwilClient.signer !== kwilSigner) throw new Error(STALE_CLIENT);\n}\n\n// shortcut: guards call/execute/waitForTx/setSigner only; wrap any new KwilActionClient method here.\nfunction boundKwilClient(kwilClient: KwilActionClient, kwilSigner: KwilSigner): KwilActionClient {\n const raw = sharedKwilClient(kwilClient);\n const cached = kwilSigner ? boundOf.get(raw)?.get(kwilSigner) : undefined;\n if (cached) return cached;\n\n const guard = (): void => assertSigner(raw, kwilSigner);\n const bound = {\n get signer() {\n guard();\n return raw.signer;\n },\n get client() {\n guard();\n return raw.client;\n },\n call: async (...args: Parameters<KwilActionClient[\"call\"]>) => {\n guard();\n return raw.call(...args);\n },\n execute: async (...args: Parameters<KwilActionClient[\"execute\"]>) => {\n guard();\n return raw.execute(...args);\n },\n waitForTx: async (txHash: string) => {\n guard();\n return raw.waitForTx(txHash);\n },\n setSigner: (signer: KwilSigner | undefined) => {\n guard();\n raw.setSigner(signer);\n },\n } as KwilActionClient;\n\n rawOf.set(bound, raw);\n if (kwilSigner) {\n const bySigner = boundOf.get(raw) ?? new WeakMap<KwilSigner, KwilActionClient>();\n bySigner.set(kwilSigner, bound);\n boundOf.set(raw, bySigner);\n }\n return bound;\n}\n\nfunction sharedEnclave(enclave: BaseProvider): BaseProvider {\n return (enclave && rawEnclaveOf.get(enclave)) || enclave;\n}\n\nfunction boundEnclave(\n enclave: BaseProvider,\n kwilClient: KwilActionClient,\n kwilSigner: KwilSigner,\n): BaseProvider {\n const raw = sharedEnclave(enclave);\n const cached = kwilSigner ? boundEnclaveOf.get(raw)?.get(kwilSigner) : undefined;\n if (cached) return cached;\n\n const bound = new Proxy(raw, {\n get(target, prop) {\n if (prop === \"then\" || typeof prop === \"symbol\") return undefined;\n const value = Reflect.get(target, prop, target);\n if (typeof value !== \"function\") {\n assertSigner(kwilClient, kwilSigner);\n return value;\n }\n return (...args: unknown[]) => {\n assertSigner(kwilClient, kwilSigner);\n return value.apply(target, args);\n };\n },\n }) as BaseProvider;\n\n rawEnclaveOf.set(bound, raw);\n if (kwilSigner) {\n const bySigner = boundEnclaveOf.get(raw) ?? new WeakMap<KwilSigner, BaseProvider>();\n bySigner.set(kwilSigner, bound);\n boundEnclaveOf.set(raw, bySigner);\n }\n return bound;\n}\n\nfunction exclusive<T>(kwilClient: KwilActionClient, run: () => Promise<T>): Promise<T> {\n const raw = sharedKwilClient(kwilClient);\n const previous = turns.get(raw) ?? Promise.resolve();\n const result = previous.then(run, run);\n turns.set(\n raw,\n result.then(\n () => undefined,\n () => undefined,\n ),\n );\n return result;\n}\n\n// `setSigner` is synchronous on the real clients. A rejected promise here is not awaited\n// by `withUserSigner` or the enclave constructor, and Node can terminate on it.\nfunction detachedSurface<T extends object>(): T {\n return new Proxy({} as T, {\n get(_target, prop) {\n if (prop === \"signer\") return undefined;\n if (prop === \"then\" || typeof prop === \"symbol\") return undefined;\n if (prop === \"client\") throw new Error(STALE_CLIENT);\n if (prop === \"setSigner\") {\n return () => {\n throw new Error(STALE_CLIENT);\n };\n }\n return async () => {\n throw new Error(STALE_CLIENT);\n };\n },\n });\n}\n\nfunction staleIdle(store: Store, blobUrl: string): idOSClientIdle {\n return new idOSClientIdle(\n store,\n detachedSurface<KwilActionClient>(),\n detachedSurface<BaseProvider>(),\n idleBlobGateway(blobUrl),\n );\n}\n\n// A replaced signer keeps the session. The signer that actually logged out must finish\n// `reset` on a later attempt; success is only returned once that reset completes.\nfunction finishLogOut(\n store: Store,\n kwilClient: KwilActionClient,\n kwilSigner: KwilSigner,\n enclaveProvider: BaseProvider,\n blobUrl: string,\n): Promise<idOSClientIdle> {\n const raw = sharedKwilClient(kwilClient);\n return exclusive(raw, async () => {\n const current = raw.signer;\n if (current !== undefined && current !== kwilSigner) return staleIdle(store, blobUrl);\n\n if (current === kwilSigner) {\n raw.setSigner(undefined);\n resetPending.add(raw);\n }\n\n if (resetPending.has(raw)) {\n await enclaveProvider.reset();\n resetPending.delete(raw);\n }\n\n // A signer installed while `reset` was in progress must not ride back on this idle client.\n if (raw.signer !== undefined && raw.signer !== kwilSigner) return staleIdle(store, blobUrl);\n\n return new idOSClientIdle(store, raw, enclaveProvider, idleBlobGateway(blobUrl));\n });\n}\n\nexport type idOSClient =\n | idOSClientConfiguration\n | idOSClientIdle\n | idOSClientWithUserSigner\n | idOSClientLoggedIn;\n\nexport class idOSClientConfiguration<Provider extends BaseProvider = IframeEnclave> {\n readonly state: \"configuration\";\n readonly chainId?: string;\n readonly nodeUrl: string;\n readonly blobGatewayUrl?: string;\n readonly enclaveOptions: Omit<Provider[\"options\"], \"mode\">;\n readonly store: Store;\n readonly enclaveProvider: BaseProvider;\n\n constructor(params: {\n chainId?: string;\n nodeUrl: string;\n /**\n * Optional blob gateway base URL. Defaults to `nodeUrl`.\n * In the browser this must share KGW's session-cookie Domain\n * (typically the same host), because reads use `credentials: \"include\"`.\n */\n blobGatewayUrl?: string;\n enclaveOptions: Omit<Provider[\"options\"], \"mode\">;\n enclaveProvider?: new (options: Omit<Provider[\"options\"], \"mode\">) => Provider;\n store?: Store;\n }) {\n this.state = \"configuration\";\n this.chainId = params.chainId;\n this.nodeUrl = params.nodeUrl;\n this.blobGatewayUrl = params.blobGatewayUrl;\n this.enclaveOptions = params.enclaveOptions;\n this.store = params.store ?? (isBrowserRuntime() ? new LocalStorageStore() : new MemoryStore());\n\n // TODO: This is a mess because of types...\n if (params.enclaveProvider) {\n this.enclaveProvider = new params.enclaveProvider({\n ...params.enclaveOptions,\n // Some of enclave providers require store to be passed in constructor\n store: this.store,\n });\n } else {\n // @ts-expect-error - In case of missing \"container\" in options, enclave will blow up\n this.enclaveProvider = new IframeEnclave(params.enclaveOptions);\n }\n }\n\n async createClient(): Promise<idOSClientIdle> {\n return idOSClientIdle.fromConfig(this);\n }\n}\n\nexport class idOSClientIdle {\n readonly state: \"idle\";\n readonly store: Store;\n readonly kwilClient: KwilActionClient;\n readonly enclaveProvider: BaseProvider;\n readonly blobGateway: BlobGateway;\n\n constructor(\n store: Store,\n kwilClient: KwilActionClient,\n enclaveProvider: BaseProvider,\n blobGateway: BlobGateway,\n ) {\n this.state = \"idle\";\n this.store = store;\n this.kwilClient = kwilClient;\n this.enclaveProvider = enclaveProvider;\n this.blobGateway = blobGateway;\n }\n\n static async fromConfig(params: idOSClientConfiguration<BaseProvider>): Promise<idOSClientIdle> {\n const createKwilClient = isBrowserRuntime() ? createWebKwilClient : createNodeKwilClient;\n const kwilClient = await createKwilClient({\n nodeUrl: params.nodeUrl,\n chainId: params.chainId,\n });\n\n await params.enclaveProvider.load();\n\n const blobGatewayUrl = params.blobGatewayUrl ?? params.nodeUrl;\n return new idOSClientIdle(\n params.store,\n kwilClient,\n params.enclaveProvider,\n idleBlobGateway(blobGatewayUrl),\n );\n }\n\n async addressHasProfile(address: string): Promise<boolean> {\n return hasProfile(this.kwilClient, { address }).then((res) => {\n if (!res) throw new Error(\"has_profile returned no rows\");\n return res.has_profile;\n });\n }\n\n async withUserSigner(_signer: Wallet): Promise<idOSClientWithUserSigner> {\n let signer = _signer;\n const [kwilSigner, walletIdentifier, walletPublicKey, walletType] =\n await createClientKwilSigner(this.store, this.kwilClient, signer);\n\n if (walletType === \"NEAR\") {\n const originalSigner = signer;\n signer = {\n signMessage: async (message: string) => {\n const signature = await signNearMessage(\n originalSigner as Parameters<typeof signNearMessage>[0],\n message,\n );\n return { signedMessage: signature } as { signedMessage: string };\n },\n } as unknown as Wallet;\n }\n\n return exclusive(this.kwilClient, async () => {\n this.kwilClient.setSigner(kwilSigner);\n return new idOSClientWithUserSigner(\n this,\n signer,\n kwilSigner,\n walletIdentifier,\n walletPublicKey,\n walletType,\n blobGatewayForSigner(this, kwilSigner),\n );\n });\n }\n\n async logOut(): Promise<idOSClientIdle> {\n return this;\n }\n}\n\nexport class idOSClientWithUserSigner implements Omit<Properties<idOSClientIdle>, \"state\"> {\n readonly state: \"with-user-signer\";\n readonly store: Store;\n readonly #kwilClient: KwilActionClient;\n readonly #enclaveProvider: BaseProvider;\n readonly signer: Wallet;\n readonly kwilSigner: KwilSigner;\n readonly walletIdentifier: string;\n readonly walletPublicKey: string | undefined;\n readonly walletType: WalletType;\n readonly blobGateway: BlobGateway;\n\n constructor(\n idOSClientIdle: idOSClientIdle,\n signer: Wallet,\n kwilSigner: KwilSigner,\n walletIdentifier: string,\n walletPublicKey: string | undefined,\n walletType: WalletType,\n blobGateway: BlobGateway,\n ) {\n this.state = \"with-user-signer\";\n this.store = idOSClientIdle.store;\n this.#kwilClient = idOSClientIdle.kwilClient;\n this.#enclaveProvider = idOSClientIdle.enclaveProvider;\n this.signer = signer;\n this.kwilSigner = kwilSigner;\n this.walletIdentifier = walletIdentifier;\n this.walletPublicKey = walletPublicKey;\n this.walletType = walletType;\n this.blobGateway = blobGateway;\n // @ts-expect-error - TODO: Fix this\n this.#enclaveProvider.setSigner(this.signer);\n }\n\n get kwilClient(): KwilActionClient {\n return boundKwilClient(this.#kwilClient, this.kwilSigner);\n }\n\n get enclaveProvider(): BaseProvider {\n return boundEnclave(this.#enclaveProvider, this.#kwilClient, this.kwilSigner);\n }\n\n async logOut(): Promise<idOSClientIdle> {\n return finishLogOut(\n this.store,\n this.#kwilClient,\n this.kwilSigner,\n this.#enclaveProvider,\n this.blobGateway.url,\n );\n }\n\n async hasProfile(): Promise<boolean> {\n // NEAR profiles are keyed by the ed25519 public key. walletIdentifier is the account id.\n let address = this.walletIdentifier;\n if (this.walletType === \"NEAR\") {\n if (!this.walletPublicKey) throw new Error(\"NEAR wallet public key is required\");\n address = this.walletPublicKey;\n }\n return hasProfile(this.kwilClient, { address }).then((res) => {\n if (!res) throw new Error(\"has_profile returned no rows\");\n return res.has_profile;\n });\n }\n\n async createUserEncryptionProfile(\n userId: string,\n forceEncryptionPasswordStore?: EncryptionPasswordStore,\n ): Promise<PublicEncryptionProfile> {\n await exclusive(this.#kwilClient, async () => {\n assertSigner(this.#kwilClient, this.kwilSigner);\n await this.enclaveProvider.reconfigure({\n mode: \"new\",\n userId,\n walletAddress: this.walletIdentifier,\n walletPublicKey: this.walletPublicKey,\n walletType: this.walletType,\n encryptionPasswordStore: forceEncryptionPasswordStore,\n expectedUserEncryptionPublicKey: undefined,\n });\n assertSigner(this.#kwilClient, this.kwilSigner);\n });\n assertSigner(this.#kwilClient, this.kwilSigner);\n return this.enclaveProvider.ensureUserEncryptionProfile();\n }\n\n async logIn(): Promise<idOSClientLoggedIn> {\n if (!(await this.hasProfile())) throw new Error(\"User does not have a profile\");\n\n const kwilUser = await getUser(this.kwilClient);\n\n return exclusive(this.#kwilClient, async () => {\n assertSigner(this.#kwilClient, this.kwilSigner);\n await this.enclaveProvider.reconfigure({\n mode: \"existing\",\n userId: kwilUser.id,\n expectedUserEncryptionPublicKey: kwilUser.recipient_encryption_public_key,\n walletAddress: this.walletIdentifier,\n walletType: this.walletType,\n encryptionPasswordStore: kwilUser.encryption_password_store,\n walletPublicKey: this.walletPublicKey,\n });\n assertSigner(this.#kwilClient, this.kwilSigner);\n return new idOSClientLoggedIn(this, kwilUser);\n });\n }\n}\n\nfunction credentialRecipientWallet(client: {\n walletType: string;\n walletIdentifier: string;\n walletPublicKey?: string;\n}): string {\n // NEAR @caller is the ed25519 public key. walletIdentifier is the account id.\n if (client.walletType === \"NEAR\") {\n if (!client.walletPublicKey) throw new Error(\"NEAR wallet public key is required\");\n return client.walletPublicKey;\n }\n return client.walletIdentifier;\n}\n\nexport class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSigner>, \"state\"> {\n readonly state: \"logged-in\";\n readonly store: Store;\n readonly #kwilClient: KwilActionClient;\n readonly #enclaveProvider: BaseProvider;\n readonly signer: Wallet;\n readonly kwilSigner: KwilSigner;\n readonly walletIdentifier: string;\n readonly walletPublicKey: string | undefined;\n readonly walletType: WalletType;\n readonly user: idOSUser;\n readonly blobGateway: BlobGateway;\n\n constructor(idOSClientWithUserSigner: idOSClientWithUserSigner, user: idOSUser) {\n this.state = \"logged-in\";\n this.store = idOSClientWithUserSigner.store;\n this.#kwilClient = sharedKwilClient(idOSClientWithUserSigner.kwilClient);\n this.#enclaveProvider = sharedEnclave(idOSClientWithUserSigner.enclaveProvider);\n this.signer = idOSClientWithUserSigner.signer;\n this.kwilSigner = idOSClientWithUserSigner.kwilSigner;\n this.walletIdentifier = idOSClientWithUserSigner.walletIdentifier;\n this.walletPublicKey = idOSClientWithUserSigner.walletPublicKey;\n this.walletType = idOSClientWithUserSigner.walletType;\n this.user = user;\n this.blobGateway = idOSClientWithUserSigner.blobGateway;\n }\n\n get kwilClient(): KwilActionClient {\n return boundKwilClient(this.#kwilClient, this.kwilSigner);\n }\n\n get enclaveProvider(): BaseProvider {\n return boundEnclave(this.#enclaveProvider, this.#kwilClient, this.kwilSigner);\n }\n\n async logOut(): Promise<idOSClientIdle> {\n return finishLogOut(\n this.store,\n this.#kwilClient,\n this.kwilSigner,\n this.#enclaveProvider,\n this.blobGateway.url,\n );\n }\n\n async requestDWGMessage(params: idOSDelegatedWriteGrant): Promise<string> {\n return dwgMessage(this.kwilClient, params).then((res) => {\n if (!res) throw new Error(\"dwg_message returned no rows\");\n return res.message;\n });\n }\n\n async createCredential(\n publicNotes: string,\n plaintextContent: Uint8Array<ArrayBufferLike>,\n // In case of credential creation on users behalf, this would be a issuer key\n issuerSigningSecretKey?: Uint8Array,\n ): Promise<Omit<idOSCredential, \"user_id\" | \"content\" | \"inserter_type\" | \"inserter_id\">> {\n const credentialId = crypto.randomUUID();\n const preliminaryCredential: PreliminaryIDOSCredential = {\n ...(await buildPreliminaryIDOSCredential({\n publicNotes,\n plaintextContent,\n recipientEncryptionPublicKey: base64Decode(this.user.recipient_encryption_public_key),\n broaderMessageFor: (publicNotesSignature, contentUri) =>\n credentialBroaderMessage(this.kwilClient, {\n public_notes_signature: publicNotesSignature,\n content_uri: contentUri,\n recipient_wallet: credentialRecipientWallet(this),\n }).then((row) => row.message),\n issuerSigningSecretKey,\n ukycStorageId: ukycStorageIdForWallet(this.walletType, this.kwilSigner),\n })),\n id: credentialId,\n };\n requireAccessTokenForUkycContent(\n preliminaryCredential.contentUri,\n this.blobGateway.hasAccessToken,\n );\n\n const requestId = crypto.randomUUID();\n\n const payload: CreatePreliminaryCredentialInput = {\n request_id: requestId,\n credential_id: preliminaryCredential.id,\n issuer_auth_public_key: preliminaryCredential.issuerAuthPublicKey,\n encryptor_public_key: preliminaryCredential.encryptorPublicKey,\n content_uri: preliminaryCredential.contentUri,\n content_size: preliminaryCredential.contentSize,\n content_hash: hexEncodeSha256Hash(plaintextContent),\n public_notes: preliminaryCredential.publicNotes,\n public_notes_signature: preliminaryCredential.publicNotesSignature,\n broader_signature: preliminaryCredential.broaderSignature,\n };\n\n await createPreliminaryCredential(this.kwilClient, payload);\n\n await this.#uploadOwnedCredentialBlobs({\n requestId,\n credentialIds: [preliminaryCredential.id],\n original: preliminaryCredential.encryptedContent,\n });\n\n return mapPreliminaryToIDOSCredential(preliminaryCredential);\n }\n\n /**\n * A lost upload response can hide a finalized credential. The user owns it, so look it up\n * by id and read its blob back: the record alone doesn't prove the gateway stored our bytes\n * (a 2xx with a CID mismatch also lands here). Rethrow the unknown outcome unless both check\n * out, including when the credential isn't visible yet, a read fails, or the read takes\n * longer than READ_BACK_TIMEOUT_MS.\n */\n async #uploadOwnedCredentialBlobs(\n params: UploadCredentialBlobsParams & { credentialIds: [string] },\n ): Promise<void> {\n try {\n await this.blobGateway.uploadCredentialBlobs(params);\n } catch (error) {\n if (!(error instanceof BlobGatewayUploadOutcomeUnknownError)) throw error;\n\n const created = await this.getCredentialById(params.credentialIds[0]).catch(() => undefined);\n if (!created?.content_uri) throw error;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), READ_BACK_TIMEOUT_MS);\n const stored = await this.blobGateway\n .fetchBlob({\n credentialId: created.id,\n contentUri: created.content_uri,\n expectedSize: created.content_size,\n signal: controller.signal,\n })\n .catch(() => undefined)\n .finally(() => clearTimeout(timer));\n const uploaded = params.original ?? params.copy;\n if (!stored || !bytesEqual(stored, uploaded)) throw error;\n }\n }\n\n async removeCredential(id: string): Promise<{ id: string }> {\n const credential = await this.getCredentialById(id);\n invariant(credential, `\"idOSCredential\" with id ${id} not found`);\n\n const contentUri = credential.content_uri ?? null;\n requireAccessTokenForUkycContent(contentUri, this.blobGateway.hasAccessToken);\n\n await removeCredential(this.kwilClient, { id });\n\n if (!contentUri) {\n return { id };\n }\n\n await this.blobGateway.deleteCredentialBlob({ credentialId: id });\n return { id };\n }\n\n async getCredentialById(id: string): Promise<idOSCredential | undefined> {\n return getCredentialOwned(this.kwilClient, { id }).then((res) => res[0]);\n }\n\n async shareCredential(\n credential: SharePreliminaryCredentialInput,\n ): Promise<SharePreliminaryCredentialInput> {\n await sharePreliminaryCredential(this.kwilClient, credential);\n return credential;\n }\n\n async getAllCredentials(): Promise<idOSCredentialListItem[]> {\n return getCredentials(this.kwilClient);\n }\n\n async getAccessGrantsOwned(): Promise<idOSGrant[]> {\n return getAccessGrantsOwned(this.kwilClient);\n }\n\n async getAttributes(): Promise<idOSUserAttribute[]> {\n return getAttributes(this.kwilClient);\n }\n\n async createAttribute(attribute: AddAttributeInput): Promise<AddAttributeInput> {\n await createAttribute(this.kwilClient, attribute);\n return attribute;\n }\n\n async getCredentialContentSha256Hash(id: string): Promise<string> {\n const credential = await this.getCredentialById(id);\n\n invariant(credential, `\"idOSCredential\" with id ${id} not found`);\n const plaintext = await this.#decryptCredentialContent(credential);\n\n return hexEncodeSha256Hash(plaintext);\n }\n\n async getCredentialContent(id: string): Promise<string> {\n const credential = await this.getCredentialById(id);\n\n invariant(credential, `\"idOSCredential\" with id ${id} not found`);\n const plaintext = await this.#decryptCredentialContent(credential);\n\n return utf8Decode(plaintext);\n }\n\n async getCredentialWithEncryptedContent(id: string): Promise<idOSCredential> {\n const credential = await this.getCredentialById(id);\n invariant(credential, `\"idOSCredential\" with id ${id} not found`);\n return this.#credentialWithInlineContent(credential);\n }\n\n async getCredentialSharedContent(id: string): Promise<string> {\n const credential = await this.getCredentialShared(id);\n\n invariant(credential, `Shared credential with id ${id} not found`);\n const plaintext = await this.#decryptCredentialContent(credential);\n\n return utf8Decode(plaintext);\n }\n\n async getGrants(\n params: Partial<GetAccessGrantsGrantedInput>,\n ): Promise<{ grants: idOSGrant[]; totalCount: number }> {\n return {\n grants: await getGrants(this.kwilClient, params),\n totalCount: await this.getGrantsCount(),\n };\n }\n\n async addWallets(params: AddWalletInput[]): Promise<AddWalletInput[]> {\n await addWallets(this.kwilClient, params);\n return params;\n }\n\n async getGrantsCount(): Promise<number> {\n return getAccessGrantsGrantedCount(this.kwilClient, {\n user_id: null,\n }).then((res) => {\n if (!res) throw new Error(\"get_access_grants_granted_count returned no rows\");\n return res.count;\n });\n }\n\n async getCredentialShared(id: string): Promise<idOSCredential | undefined> {\n return getCredentialShared(this.kwilClient, { id }).then((res) => res[0]);\n }\n\n async revokeAccessGrant(id: string): Promise<{ id: string }> {\n await revokeAccessGrant(this.kwilClient, { id });\n return { id };\n }\n\n async addWalletMessage(params: AddWalletMessageInput): Promise<string> {\n const result = await requestAddWalletMessage(this.kwilClient, params);\n return result.message;\n }\n\n async addWallet(params: AddWalletInput): Promise<AddWalletInput> {\n await addWallet(this.kwilClient, params);\n\n // we don't need to add the wallet to MPC if the user is not using MPC\n if (this.user.encryption_password_store !== \"mpc\") {\n console.log(\"MPC is not enabled or the user is not using MPC\");\n return params;\n }\n\n if (!params.wallet_type) {\n throw new Error(\"Wallet type is required for MPC users\");\n }\n\n const messageToSign = await this.enclaveProvider.addAddressMessageToSign(\n params.address,\n params.public_key ?? undefined,\n params.wallet_type,\n );\n\n const signature = await this.enclaveProvider.signTypedData(\n messageToSign.domain,\n messageToSign.types,\n messageToSign.value,\n );\n\n const result = await this.enclaveProvider.addAddressToMpcSecret(\n this.user.id,\n messageToSign.value,\n signature,\n );\n\n if (result !== \"success\") {\n console.error(`Failed to add wallet to MPC: ${result}`);\n }\n\n return params;\n }\n\n async getWallets(): Promise<GetWalletsOutput[]> {\n return getWallets(this.kwilClient);\n }\n\n async removeWallet(id: string): Promise<{ id: string }> {\n const wallets = await this.getWallets();\n const wallet = wallets.find((wallet) => wallet.id === id);\n if (!wallet) {\n throw new Error(`Wallet with id ${id} not found`);\n }\n\n await removeWallet(this.kwilClient, { id });\n\n // we don't need to add the wallet to MPC if the user is not using MPC\n if (this.user.encryption_password_store !== \"mpc\") {\n console.log(\"MPC is not enabled or the user is not using MPC\");\n return { id };\n }\n\n const messageToSign = await this.enclaveProvider.removeAddressMessageToSign(\n wallet.address,\n wallet.public_key ?? undefined,\n wallet.wallet_type,\n );\n const signature = await this.enclaveProvider.signTypedData(\n messageToSign.domain,\n messageToSign.types,\n messageToSign.value,\n );\n const result = await this.enclaveProvider.removeAddressFromMpcSecret(\n wallet.user_id,\n messageToSign.value,\n signature,\n );\n if (result !== \"success\") {\n console.error(`Failed to add wallet to MPC: ${result}`);\n }\n\n return { id };\n }\n\n async removeWallets(ids: string[]): Promise<string[]> {\n for (const id of ids) {\n await this.removeWallet(id);\n }\n\n return ids;\n }\n\n async filterCredentials(requirements: {\n acceptedIssuers: {\n authPublicKey: string;\n }[];\n publicNotesFieldFilters?: {\n pick: Parameters<typeof recordFilter>[1];\n omit: Parameters<typeof recordFilter>[2];\n };\n privateFieldFilters?: {\n pick: Parameters<typeof recordFilter>[1];\n omit: Parameters<typeof recordFilter>[2];\n };\n /** @deprecated The level leaves out self-attested data. Use `claimsFilter` instead. */\n credentialLevelOrHigherFilter?: {\n userLevel: BaseLevel;\n requiredAddons: Addon[];\n };\n /** Accepted sources per claim, e.g. `{ email: [\"VERIFIED\", \"MANUAL\"] }`. See `matchClaims`. */\n claimsFilter?: ClaimRequirements;\n }): Promise<idOSCredentialListItem[]> {\n const credentials = await this.getAllCredentials();\n const originalCredentials = credentials.filter(\n (cred) => !cred.original_id && !!cred.public_notes,\n );\n\n // invariant(originalCredentials.length, \"No original credentials found\");\n let result = originalCredentials.filter((cred) => {\n return requirements.acceptedIssuers?.some(\n (issuer) => issuer.authPublicKey === cred.issuer_auth_public_key,\n );\n });\n\n const publicNotesFieldFilters = requirements.publicNotesFieldFilters;\n const credentialLevelOrHigherFilter = requirements.credentialLevelOrHigherFilter;\n const privateFieldFilters = requirements.privateFieldFilters;\n const claimsFilter = requirements.claimsFilter;\n\n if (claimsFilter) {\n result = result.filter((credential) => {\n let publicNotes: Parameters<typeof matchClaims>[1];\n\n try {\n publicNotes = JSON.parse(credential.public_notes);\n } catch (_) {\n throw new Error(`Credential ${credential.id} has non-JSON public notes.`);\n }\n\n return matchClaims(claimsFilter, publicNotes);\n });\n }\n\n if (credentialLevelOrHigherFilter) {\n result = result.filter((credential) => {\n let publicNotes: Record<string, string>;\n\n try {\n publicNotes = JSON.parse(credential.public_notes);\n } catch (_) {\n throw new Error(`Credential ${credential.id} has non-JSON public notes.`);\n }\n\n return matchLevelOrHigher(\n credentialLevelOrHigherFilter.userLevel,\n credentialLevelOrHigherFilter.requiredAddons,\n publicNotes.level,\n );\n });\n }\n\n if (\n publicNotesFieldFilters &&\n (Object.keys(publicNotesFieldFilters.pick).length > 0 ||\n Object.keys(publicNotesFieldFilters.omit).length > 0)\n ) {\n result = result.filter((credential) => {\n let publicNotes: Record<string, string>;\n\n try {\n publicNotes = JSON.parse(credential.public_notes);\n } catch (_) {\n throw new Error(`Credential ${credential.id} has non-JSON public notes.`);\n }\n\n return recordFilter(\n publicNotes,\n publicNotesFieldFilters.pick,\n publicNotesFieldFilters.omit,\n );\n });\n }\n\n // Private field filtering requires decryption and the full idOS credential content\n // it's most \"expensive\", since it requires a roundtrip to the nodes and roundtrip to enclave.\n if (\n privateFieldFilters &&\n (Object.keys(privateFieldFilters.pick).length > 0 ||\n Object.keys(privateFieldFilters.omit).length > 0)\n ) {\n const fullCredentials = await Promise.all(\n result.map((credential) => this.getCredentialById(credential.id)),\n );\n\n // Check for undefined, it will be sign of some internal error\n invariant(\n fullCredentials.every((cred) => cred !== undefined),\n \"Some credentials could not be fetched in full form for private field filtering\",\n );\n\n const matches = await this.enclaveProvider.filterCredentials(\n await Promise.all(\n fullCredentials.map((credential) => this.#credentialWithInlineContent(credential)),\n ),\n privateFieldFilters,\n );\n\n result = result.filter((credential) =>\n matches.some((matchedCredential) => matchedCredential.id === credential.id),\n );\n }\n\n return result;\n }\n\n async requestAccessGrant(\n credentialId: string,\n {\n consumerEncryptionPublicKey,\n consumerAuthPublicKey,\n lockedUntil = 0,\n }: {\n consumerEncryptionPublicKey: string;\n consumerAuthPublicKey: string;\n lockedUntil?: number;\n },\n ): Promise<SharePreliminaryCredentialInput> {\n const credential = await this.getCredentialById(credentialId);\n\n invariant(credential, `\"idOSCredential\" with id ${credentialId} not found`);\n\n const plaintextContent = await this.#decryptCredentialContent(credential);\n const contentHash = hexEncodeSha256Hash(plaintextContent);\n\n await this.enclaveProvider.ensureUserEncryptionProfile();\n\n const { content, encryptorPublicKey } = await this.enclaveProvider.encrypt(\n plaintextContent,\n base64Decode(consumerEncryptionPublicKey),\n );\n\n // User issues the shared copy: sign content_uri with an ephemeral user-side key.\n // Copy issuer_auth_public_key need not match the original credential's issuer.\n const copyId = crypto.randomUUID();\n const ukycStorageId = ukycStorageIdForWallet(this.walletType, this.kwilSigner);\n const copyReference = ukycStorageId\n ? createUkycContentReference(ukycStorageId, content)\n : await createBlobContentReference(content);\n requireAccessTokenForUkycContent(copyReference.uri, this.blobGateway.hasAccessToken);\n const signedReference = await buildEphemeralSignedCredentialContentReference(\n \"\",\n copyReference.uri,\n (publicNotesSignature, contentUri) =>\n credentialBroaderMessage(this.kwilClient, {\n public_notes_signature: publicNotesSignature,\n content_uri: contentUri,\n recipient_wallet: credentialRecipientWallet(this),\n }).then((row) => row.message),\n );\n\n // Integrator-supplied. ed25519 @caller is lowercase hex; after exact grantee\n // matching, uppercase hex would store a grant the consumer cannot read. Other\n // identifier encodings (NEAR, XRPL, Stellar, MM) are case-sensitive, so leave them.\n const granteeWalletIdentifier = /^[0-9a-fA-F]{64}$/.test(consumerAuthPublicKey)\n ? consumerAuthPublicKey.toLowerCase()\n : consumerAuthPublicKey;\n\n const preliminaryCredential: SharePreliminaryCredentialInput = {\n ...signedReference,\n request_id: crypto.randomUUID(),\n copy_id: copyId,\n original_id: credential.id,\n content_uri: copyReference.uri,\n content_size: copyReference.size,\n encryptor_public_key: base64Encode(encryptorPublicKey),\n grantee_wallet_identifier: granteeWalletIdentifier,\n locked_until: lockedUntil,\n content_hash: contentHash,\n };\n\n await this.shareCredential(preliminaryCredential);\n await this.#uploadOwnedCredentialBlobs({\n requestId: preliminaryCredential.request_id,\n credentialIds: [copyId],\n copy: content,\n });\n\n return preliminaryCredential;\n }\n\n async #credentialWithInlineContent(credential: idOSCredential): Promise<idOSCredential> {\n if (credential.content) {\n return credential;\n }\n\n return {\n ...credential,\n content: base64Encode(await this.#getCredentialEncryptedContent(credential)),\n content_uri: null,\n content_size: null,\n };\n }\n\n async #decryptCredentialContent(credential: idOSCredential): Promise<Uint8Array> {\n await this.enclaveProvider.ensureUserEncryptionProfile();\n\n return this.enclaveProvider.decrypt(\n await this.#getCredentialEncryptedContent(credential),\n base64Decode(credential.encryptor_public_key),\n );\n }\n\n async #getCredentialEncryptedContent(credential: idOSCredential): Promise<Uint8Array> {\n return resolveCredentialEncryptedContent(credential, this.blobGateway);\n }\n}\n\nexport type {\n Claim,\n ClaimRequirements,\n Claims,\n ClaimSource,\n ClaimSources,\n idOSDelegatedWriteGrant,\n DelegatedWriteGrantBaseParams,\n idOSCredential,\n idOSCredentialListItem,\n idOSGrant,\n idOSUser,\n idOSUserAttribute,\n idOSWallet,\n};\n\nexport { signNearMessage, toDelegatedWriteGrantBaseParams };\n\nexport function createIDOSClient(params: {\n nodeUrl: string;\n /**\n * Optional blob gateway base URL. Defaults to `nodeUrl`.\n * In the browser this must share KGW's session-cookie Domain\n * (typically the same host), because reads use `credentials: \"include\"`.\n */\n blobGatewayUrl?: string;\n enclaveOptions: Omit<IframeEnclave[\"options\"], \"mode\">;\n}): idOSClientConfiguration<IframeEnclave> {\n return new idOSClientConfiguration({\n nodeUrl: params.nodeUrl,\n blobGatewayUrl: params.blobGatewayUrl,\n enclaveOptions: params.enclaveOptions,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["createAttribute","requestAddWalletMessage"],"sources":["../src/enclave/iframe-enclave.ts","../src/index.ts"],"sourcesContent":["import type { idOSCredentialRecord as idOSCredential } from \"@idos-network/credentials/types\";\nimport type {\n AddAddressMessageToSign,\n AddAddressSignatureMessage,\n RemoveAddressMessageToSign,\n RemoveAddressSignatureMessage,\n} from \"@idos-network/enclave/mpc\";\n\nimport {\n BaseProvider,\n type EnclaveOptions,\n type PublicEncryptionProfile,\n} from \"@idos-network/enclave\";\n\nimport type { BaseProviderMethodArgs, BaseProviderMethodReturn } from \"./helpers\";\n\nexport interface IframeEnclaveOptions extends EnclaveOptions {\n container: string;\n url?: string;\n throwOnUserCancelUnlock?: boolean;\n}\n\nexport class IframeEnclave extends BaseProvider<IframeEnclaveOptions> {\n private container: string;\n private iframe: HTMLIFrameElement;\n private hostUrl: URL;\n private bound = false;\n\n constructor(options: IframeEnclaveOptions) {\n super(options);\n\n if (!this.options.container) {\n throw new Error(\"container is required\");\n }\n\n this.container = this.options.container;\n this.hostUrl = new URL(this.options.url ?? \"https://enclave.idos.network\");\n this.iframe = document.createElement(\"iframe\");\n this.iframe.id = \"idos-enclave-iframe\";\n }\n\n /** @see parent method */\n async load(): Promise<void> {\n // First we have to create and load the iframe\n await this.createAndLoadIframe();\n\n // Load the enclave from the store (trigger load() method in the iframe)\n await this.requestToEnclave(\"load\");\n\n // Pass current options\n await this.reconfigure();\n\n // Bind the message listener to the iframe (in case iframe -> enclave comm)\n await this.bindMessageListener();\n }\n\n /**\n * Embedding pages cannot reset enclave storage. The iframe rejects `reset`\n * because it deletes every idOS-* key with no origin check.\n */\n async reset(): Promise<void> {\n throw new Error(\"Embedding pages cannot reset enclave storage\");\n }\n\n /** @override parent method to call iframe */\n async reconfigure(options: Omit<IframeEnclaveOptions, \"container\" | \"url\"> = {}): Promise<void> {\n super.reconfigure(options);\n await this.requestToEnclave(\"reconfigure\", this.options);\n }\n\n /** @override parent method to call iframe */\n async confirm(message: string): Promise<boolean> {\n this.showEnclave();\n\n try {\n return await this.requestToEnclave(\"confirm\", message);\n } catch (error) {\n console.error(error);\n return false;\n } finally {\n this.hideEnclave();\n }\n }\n\n /** @override parent method to call iframe */\n async filterCredentials(\n credentials: idOSCredential[],\n privateFieldFilters: { pick: Record<string, unknown[]>; omit: Record<string, unknown[]> },\n ): Promise<idOSCredential[]> {\n return await this.requestToEnclave(\"filterCredentials\", credentials, privateFieldFilters);\n }\n\n /** @override parent method to call iframe */\n async encrypt(\n message: Uint8Array,\n receiverPublicKey: Uint8Array,\n ): Promise<{ content: Uint8Array; encryptorPublicKey: Uint8Array }> {\n return this.requestToEnclave(\"encrypt\", message, receiverPublicKey);\n }\n\n /** @override parent method to call iframe */\n async decrypt(\n message: Uint8Array,\n senderPublicKey: Uint8Array,\n ): Promise<Uint8Array<ArrayBufferLike>> {\n return this.requestToEnclave(\"decrypt\", message, senderPublicKey);\n }\n\n /** @override parent method to call iframe */\n async backupUserEncryptionProfile(): Promise<void> {\n this.showEnclave();\n\n try {\n await this.requestToEnclave(\"backupUserEncryptionProfile\");\n } catch (error) {\n console.error(error);\n } finally {\n this.hideEnclave();\n }\n }\n\n /** @override parent method to call iframe */\n async ensureUserEncryptionProfile(): Promise<PublicEncryptionProfile> {\n this.showEnclave();\n\n try {\n return await this.requestToEnclave(\"ensureUserEncryptionProfile\");\n } finally {\n this.hideEnclave();\n }\n }\n\n async addAddressMessageToSign(\n address: string,\n publicKey: string | undefined,\n addressToAddType: string,\n ): Promise<AddAddressMessageToSign> {\n return this.requestToEnclave(\"addAddressMessageToSign\", address, publicKey, addressToAddType);\n }\n\n async removeAddressMessageToSign(\n address: string,\n publicKey: string | undefined,\n addressToRemoveType: string,\n ): Promise<RemoveAddressMessageToSign> {\n return this.requestToEnclave(\n \"removeAddressMessageToSign\",\n address,\n publicKey,\n addressToRemoveType,\n );\n }\n\n async addAddressToMpcSecret(\n userId: string,\n message: AddAddressSignatureMessage,\n signature: string,\n ): Promise<string> {\n return this.requestToEnclave(\"addAddressToMpcSecret\", userId, message, signature);\n }\n\n async removeAddressFromMpcSecret(\n userId: string,\n message: RemoveAddressSignatureMessage,\n signature: string,\n ): Promise<string> {\n return this.requestToEnclave(\"removeAddressFromMpcSecret\", userId, message, signature);\n }\n\n private async createAndLoadIframe(): Promise<void> {\n const container = document.querySelector(this.container);\n\n if (!container) {\n throw new Error(`Can't find container with selector ${this.container}`);\n }\n\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy#directives\n const permissionsPolicies = [\"publickey-credentials-get\", \"storage-access\"];\n\n // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#sandbox\n const liftedSandboxRestrictions = [\n \"forms\",\n \"modals\",\n \"popups\",\n \"popups-to-escape-sandbox\",\n \"same-origin\",\n \"scripts\",\n ].map((toLift) => `allow-${toLift}`);\n\n // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#referrerpolicy\n const referrerPolicy = \"origin\";\n\n const styles = {\n \"aspect-ratio\": \"4/1\",\n \"background-color\": \"transparent\",\n border: \"none\",\n display: \"block\",\n overflow: \"hidden\",\n width: \"100%\",\n };\n\n this.iframe.allow = permissionsPolicies.join(\"; \");\n this.iframe.referrerPolicy = referrerPolicy;\n this.iframe.sandbox.add(...liftedSandboxRestrictions);\n this.iframe.src = this.hostUrl.toString();\n for (const [k, v] of Object.entries(styles)) {\n this.iframe.style.setProperty(k, v);\n }\n\n let el: HTMLElement | null;\n // oxlint-disable-next-line no-cond-assign -- it's on purpose\n while ((el = document.getElementById(this.iframe.id))) {\n console.log(\"reinstalling idOS iframe...\");\n container.removeChild(el);\n }\n container.appendChild(this.iframe);\n\n return new Promise((resolve) =>\n this.iframe.addEventListener(\n \"load\",\n () => {\n resolve();\n },\n { once: true },\n ),\n );\n }\n\n private showEnclave(): void {\n // oxlint-disable-next-line typescript/no-non-null-assertion -- Make the explosion visible.\n this.iframe.parentElement!.classList.add(\"visible\");\n }\n\n private hideEnclave(): void {\n // oxlint-disable-next-line typescript/no-non-null-assertion -- Make the explosion visible.\n this.iframe.parentElement!.classList.remove(\"visible\");\n }\n\n private async requestToEnclave<TMethod extends keyof BaseProviderMethodArgs>(\n method: TMethod,\n ...args: BaseProviderMethodArgs[TMethod]\n ): Promise<BaseProviderMethodReturn[TMethod]> {\n return new Promise((resolve, reject) => {\n const { port1, port2 } = new MessageChannel();\n\n port1.onmessage = ({ data }) => {\n port1.close();\n // oxlint-disable-next-line no-unused-expressions\n data.error ? reject(data.error) : resolve(data.result);\n };\n\n // oxlint-disable-next-line typescript/no-non-null-assertion -- Make the explosion visible.\n this.iframe.contentWindow!.postMessage(\n {\n method,\n data: args,\n },\n this.hostUrl.origin,\n [port2],\n );\n });\n }\n\n private bindMessageListener(): void {\n if (!this.bound) window.addEventListener(\"message\", this.onMessage.bind(this));\n this.bound = true;\n }\n\n private async onMessage(message: MessageEvent): Promise<void> {\n // We can't be sure about the message and the content\n // so we have to validate it carefully.\n if (!message || !message.data || typeof message.data !== \"object\") return;\n\n if (message.data.type !== \"idOS:signTypedData\" || message.origin !== this.hostUrl.origin)\n return;\n\n const payload = message.data.payload;\n const signature = await this.signTypedData(payload.domain, payload.types, payload.value);\n await this.requestToEnclave(\"signTypedDataResponse\", signature);\n }\n}\n","import type {\n BaseProvider,\n EncryptionPasswordStore,\n PublicEncryptionProfile,\n} from \"@idos-network/enclave\";\n\nimport {\n buildEphemeralSignedCredentialContentReference,\n buildPreliminaryIDOSCredential,\n mapPreliminaryToIDOSCredential,\n matchClaims,\n matchLevelOrHigher,\n type PreliminaryIDOSCredential,\n recordFilter,\n type BaseLevel,\n type Addon,\n type Claim,\n type ClaimRequirements,\n type Claims,\n type ClaimSource,\n type ClaimSources,\n} from \"@idos-network/credentials/utils\";\nimport {\n createClientKwilSigner,\n createKgwAuthenticatedBlobGateway,\n createNodeKwilClient,\n createWebKwilClient,\n type KwilActionClient,\n signNearMessage,\n type Wallet,\n} from \"@idos-network/kwil-infra\";\nimport {\n type AddAttributeInput,\n type AddWalletInput,\n type AddWalletMessageInput,\n addWallet,\n addWalletMessage as requestAddWalletMessage,\n addWallets,\n addAttribute as createAttribute,\n createPreliminaryCredential,\n credentialBroaderMessage,\n type CreatePreliminaryCredentialInput,\n dwgMessage,\n type GetAccessGrantsGrantedInput,\n type GetWalletsOutput,\n getAccessGrantsGrantedCount,\n getAccessGrantsOwned,\n getAttributes,\n getCredentialOwned,\n getCredentialShared,\n getCredentials,\n getGrants,\n getUser,\n getWallets,\n hasProfile,\n type idOSCredential,\n type idOSCredentialListItem,\n type idOSDelegatedWriteGrant,\n type DelegatedWriteGrantBaseParams,\n toDelegatedWriteGrantBaseParams,\n type idOSGrant,\n type idOSUser,\n type idOSUserAttribute,\n type idOSWallet,\n removeCredential,\n removeWallet,\n revokeAccessGrant,\n type SharePreliminaryCredentialInput,\n sharePreliminaryCredential,\n type WalletType,\n} from \"@idos-network/kwil-infra/actions\";\nimport { NodeKwil, type KwilSigner } from \"@idos-network/kwil-js\";\nimport {\n BlobGateway,\n BlobGatewayUploadOutcomeUnknownError,\n createBlobContentReference,\n isUkycContentUri,\n resolveCredentialEncryptedContent,\n type UploadCredentialBlobsParams,\n} from \"@idos-network/utils/blob-gateway\";\nimport {\n base64Decode,\n base64Encode,\n hexEncodeSha256Hash,\n utf8Decode,\n} from \"@idos-network/utils/codecs\";\nimport { LocalStorageStore, MemoryStore, type Store } from \"@idos-network/utils/store\";\nimport invariant from \"tiny-invariant\";\n\nimport { IframeEnclave } from \"./enclave/iframe-enclave\";\nexport { IframeEnclave };\n\ntype Properties<T> = {\n // oxlint-disable-next-line typescript/no-restricted-types -- All functions are to be removed.\n [K in keyof T as Exclude<T[K], Function> extends never ? never : K]: T[K];\n};\n\nfunction isBrowserRuntime(): boolean {\n return typeof window !== \"undefined\";\n}\n\nfunction usesNodeKwil(kwilClient: KwilActionClient): boolean {\n return kwilClient.client instanceof NodeKwil;\n}\n\nfunction idleBlobGateway(url: string): BlobGateway {\n if (!isBrowserRuntime()) {\n return new BlobGateway({ url });\n }\n\n return new BlobGateway({\n url,\n // Browser blob reads need the KGW HttpOnly session cookie. That only works if the\n // blob gateway is covered by the cookie's Domain (typically same host as nodeUrl/KGW).\n fetchFn: (input, init) => fetch(input, { ...init, credentials: \"include\" }),\n });\n}\n\nfunction blobGatewayForSigner(idle: idOSClientIdle, kwilSigner: KwilSigner): BlobGateway {\n if (usesNodeKwil(idle.kwilClient)) {\n return createKgwAuthenticatedBlobGateway({\n url: idle.blobGateway.url,\n kwilClient: idle.kwilClient,\n signer: kwilSigner,\n });\n }\n\n return idle.blobGateway;\n}\n\n// Deadline for reading a blob back after an unknown upload outcome. A slower read leaves the\n// outcome unknown, which callers already have to handle, instead of hanging the call.\nconst READ_BACK_TIMEOUT_MS = 60_000;\n\nfunction bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n return a.byteLength === b.byteLength && a.every((byte, index) => byte === b[index]);\n}\n\nconst STALE_CLIENT =\n \"This idOS client is stale: another signer was set or it was logged out. Use the client returned by the latest `withUserSigner()`.\";\n\n// Wrappers from one idle client share its Kwil client and enclave. `rawOf` unwraps the\n// guard below; `turns` keeps signer replacement and enclave reconfiguration from interleaving.\nconst rawOf = new WeakMap<KwilActionClient, KwilActionClient>();\nconst boundOf = new WeakMap<KwilActionClient, WeakMap<KwilSigner, KwilActionClient>>();\nconst rawEnclaveOf = new WeakMap<BaseProvider, BaseProvider>();\nconst boundEnclaveOf = new WeakMap<BaseProvider, WeakMap<KwilSigner, BaseProvider>>();\nconst turns = new WeakMap<KwilActionClient, Promise<void>>();\nconst resetPending = new WeakSet<KwilActionClient>();\n\nfunction sharedKwilClient(kwilClient: KwilActionClient): KwilActionClient {\n return rawOf.get(kwilClient) ?? kwilClient;\n}\n\nfunction assertSigner(kwilClient: KwilActionClient, kwilSigner: KwilSigner): void {\n if (kwilClient.signer !== kwilSigner) throw new Error(STALE_CLIENT);\n}\n\n// shortcut: guards call/execute/waitForTx/setSigner only; wrap any new KwilActionClient method here.\nfunction boundKwilClient(kwilClient: KwilActionClient, kwilSigner: KwilSigner): KwilActionClient {\n const raw = sharedKwilClient(kwilClient);\n const cached = kwilSigner ? boundOf.get(raw)?.get(kwilSigner) : undefined;\n if (cached) return cached;\n\n const guard = (): void => assertSigner(raw, kwilSigner);\n const bound = {\n get signer() {\n guard();\n return raw.signer;\n },\n get client() {\n guard();\n return raw.client;\n },\n call: async (...args: Parameters<KwilActionClient[\"call\"]>) => {\n guard();\n return raw.call(...args);\n },\n execute: async (...args: Parameters<KwilActionClient[\"execute\"]>) => {\n guard();\n return raw.execute(...args);\n },\n waitForTx: async (txHash: string) => {\n guard();\n return raw.waitForTx(txHash);\n },\n setSigner: (signer: KwilSigner | undefined) => {\n guard();\n raw.setSigner(signer);\n },\n } as KwilActionClient;\n\n rawOf.set(bound, raw);\n if (kwilSigner) {\n const bySigner = boundOf.get(raw) ?? new WeakMap<KwilSigner, KwilActionClient>();\n bySigner.set(kwilSigner, bound);\n boundOf.set(raw, bySigner);\n }\n return bound;\n}\n\nfunction sharedEnclave(enclave: BaseProvider): BaseProvider {\n return (enclave && rawEnclaveOf.get(enclave)) || enclave;\n}\n\nfunction boundEnclave(\n enclave: BaseProvider,\n kwilClient: KwilActionClient,\n kwilSigner: KwilSigner,\n): BaseProvider {\n const raw = sharedEnclave(enclave);\n const cached = kwilSigner ? boundEnclaveOf.get(raw)?.get(kwilSigner) : undefined;\n if (cached) return cached;\n\n const bound = new Proxy(raw, {\n get(target, prop) {\n if (prop === \"then\" || typeof prop === \"symbol\") return undefined;\n const value = Reflect.get(target, prop, target);\n if (typeof value !== \"function\") {\n assertSigner(kwilClient, kwilSigner);\n return value;\n }\n return (...args: unknown[]) => {\n assertSigner(kwilClient, kwilSigner);\n return value.apply(target, args);\n };\n },\n }) as BaseProvider;\n\n rawEnclaveOf.set(bound, raw);\n if (kwilSigner) {\n const bySigner = boundEnclaveOf.get(raw) ?? new WeakMap<KwilSigner, BaseProvider>();\n bySigner.set(kwilSigner, bound);\n boundEnclaveOf.set(raw, bySigner);\n }\n return bound;\n}\n\nfunction exclusive<T>(kwilClient: KwilActionClient, run: () => Promise<T>): Promise<T> {\n const raw = sharedKwilClient(kwilClient);\n const previous = turns.get(raw) ?? Promise.resolve();\n const result = previous.then(run, run);\n turns.set(\n raw,\n result.then(\n () => undefined,\n () => undefined,\n ),\n );\n return result;\n}\n\n// `setSigner` is synchronous on the real clients. A rejected promise here is not awaited\n// by `withUserSigner` or the enclave constructor, and Node can terminate on it.\nfunction detachedSurface<T extends object>(): T {\n return new Proxy({} as T, {\n get(_target, prop) {\n if (prop === \"signer\") return undefined;\n if (prop === \"then\" || typeof prop === \"symbol\") return undefined;\n if (prop === \"client\") throw new Error(STALE_CLIENT);\n if (prop === \"setSigner\") {\n return () => {\n throw new Error(STALE_CLIENT);\n };\n }\n return async () => {\n throw new Error(STALE_CLIENT);\n };\n },\n });\n}\n\nfunction staleIdle(store: Store, blobUrl: string): idOSClientIdle {\n return new idOSClientIdle(\n store,\n detachedSurface<KwilActionClient>(),\n detachedSurface<BaseProvider>(),\n idleBlobGateway(blobUrl),\n );\n}\n\n// A replaced signer keeps the session. The signer that actually logged out must finish\n// `reset` on a later attempt; success is only returned once that reset completes.\nfunction finishLogOut(\n store: Store,\n kwilClient: KwilActionClient,\n kwilSigner: KwilSigner,\n enclaveProvider: BaseProvider,\n blobUrl: string,\n): Promise<idOSClientIdle> {\n const raw = sharedKwilClient(kwilClient);\n return exclusive(raw, async () => {\n const current = raw.signer;\n if (current !== undefined && current !== kwilSigner) return staleIdle(store, blobUrl);\n\n if (current === kwilSigner) {\n raw.setSigner(undefined);\n resetPending.add(raw);\n }\n\n if (resetPending.has(raw)) {\n await enclaveProvider.reset();\n resetPending.delete(raw);\n }\n\n // A signer installed while `reset` was in progress must not ride back on this idle client.\n if (raw.signer !== undefined && raw.signer !== kwilSigner) return staleIdle(store, blobUrl);\n\n return new idOSClientIdle(store, raw, enclaveProvider, idleBlobGateway(blobUrl));\n });\n}\n\nexport type idOSClient =\n | idOSClientConfiguration\n | idOSClientIdle\n | idOSClientWithUserSigner\n | idOSClientLoggedIn;\n\nexport class idOSClientConfiguration<Provider extends BaseProvider = IframeEnclave> {\n readonly state: \"configuration\";\n readonly chainId?: string;\n readonly nodeUrl: string;\n readonly blobGatewayUrl?: string;\n readonly enclaveOptions: Omit<Provider[\"options\"], \"mode\">;\n readonly store: Store;\n readonly enclaveProvider: BaseProvider;\n\n constructor(params: {\n chainId?: string;\n nodeUrl: string;\n /**\n * Optional blob gateway base URL. Defaults to `nodeUrl`.\n * In the browser this must share KGW's session-cookie Domain\n * (typically the same host), because reads use `credentials: \"include\"`.\n */\n blobGatewayUrl?: string;\n enclaveOptions: Omit<Provider[\"options\"], \"mode\">;\n enclaveProvider?: new (options: Omit<Provider[\"options\"], \"mode\">) => Provider;\n store?: Store;\n }) {\n this.state = \"configuration\";\n this.chainId = params.chainId;\n this.nodeUrl = params.nodeUrl;\n this.blobGatewayUrl = params.blobGatewayUrl;\n this.enclaveOptions = params.enclaveOptions;\n this.store = params.store ?? (isBrowserRuntime() ? new LocalStorageStore() : new MemoryStore());\n\n // TODO: This is a mess because of types...\n if (params.enclaveProvider) {\n this.enclaveProvider = new params.enclaveProvider({\n ...params.enclaveOptions,\n // Some of enclave providers require store to be passed in constructor\n store: this.store,\n });\n } else {\n // @ts-expect-error - In case of missing \"container\" in options, enclave will blow up\n this.enclaveProvider = new IframeEnclave(params.enclaveOptions);\n }\n }\n\n async createClient(): Promise<idOSClientIdle> {\n return idOSClientIdle.fromConfig(this);\n }\n}\n\nexport class idOSClientIdle {\n readonly state: \"idle\";\n readonly store: Store;\n readonly kwilClient: KwilActionClient;\n readonly enclaveProvider: BaseProvider;\n readonly blobGateway: BlobGateway;\n\n constructor(\n store: Store,\n kwilClient: KwilActionClient,\n enclaveProvider: BaseProvider,\n blobGateway: BlobGateway,\n ) {\n this.state = \"idle\";\n this.store = store;\n this.kwilClient = kwilClient;\n this.enclaveProvider = enclaveProvider;\n this.blobGateway = blobGateway;\n }\n\n static async fromConfig(params: idOSClientConfiguration<BaseProvider>): Promise<idOSClientIdle> {\n const createKwilClient = isBrowserRuntime() ? createWebKwilClient : createNodeKwilClient;\n const kwilClient = await createKwilClient({\n nodeUrl: params.nodeUrl,\n chainId: params.chainId,\n });\n\n await params.enclaveProvider.load();\n\n const blobGatewayUrl = params.blobGatewayUrl ?? params.nodeUrl;\n return new idOSClientIdle(\n params.store,\n kwilClient,\n params.enclaveProvider,\n idleBlobGateway(blobGatewayUrl),\n );\n }\n\n async addressHasProfile(address: string): Promise<boolean> {\n return hasProfile(this.kwilClient, { address }).then((res) => {\n if (!res) throw new Error(\"has_profile returned no rows\");\n return res.has_profile;\n });\n }\n\n async withUserSigner(_signer: Wallet): Promise<idOSClientWithUserSigner> {\n let signer = _signer;\n const [kwilSigner, walletIdentifier, walletPublicKey, walletType] =\n await createClientKwilSigner(this.store, this.kwilClient, signer);\n\n if (walletType === \"NEAR\") {\n const originalSigner = signer;\n signer = {\n signMessage: async (message: string) => {\n const signature = await signNearMessage(\n originalSigner as Parameters<typeof signNearMessage>[0],\n message,\n );\n return { signedMessage: signature } as { signedMessage: string };\n },\n } as unknown as Wallet;\n }\n\n return exclusive(this.kwilClient, async () => {\n this.kwilClient.setSigner(kwilSigner);\n return new idOSClientWithUserSigner(\n this,\n signer,\n kwilSigner,\n walletIdentifier,\n walletPublicKey,\n walletType,\n blobGatewayForSigner(this, kwilSigner),\n );\n });\n }\n\n async logOut(): Promise<idOSClientIdle> {\n return this;\n }\n}\n\nexport class idOSClientWithUserSigner implements Omit<Properties<idOSClientIdle>, \"state\"> {\n readonly state: \"with-user-signer\";\n readonly store: Store;\n readonly #kwilClient: KwilActionClient;\n readonly #enclaveProvider: BaseProvider;\n readonly signer: Wallet;\n readonly kwilSigner: KwilSigner;\n readonly walletIdentifier: string;\n readonly walletPublicKey: string | undefined;\n readonly walletType: WalletType;\n readonly blobGateway: BlobGateway;\n\n constructor(\n idOSClientIdle: idOSClientIdle,\n signer: Wallet,\n kwilSigner: KwilSigner,\n walletIdentifier: string,\n walletPublicKey: string | undefined,\n walletType: WalletType,\n blobGateway: BlobGateway,\n ) {\n this.state = \"with-user-signer\";\n this.store = idOSClientIdle.store;\n this.#kwilClient = idOSClientIdle.kwilClient;\n this.#enclaveProvider = idOSClientIdle.enclaveProvider;\n this.signer = signer;\n this.kwilSigner = kwilSigner;\n this.walletIdentifier = walletIdentifier;\n this.walletPublicKey = walletPublicKey;\n this.walletType = walletType;\n this.blobGateway = blobGateway;\n // @ts-expect-error - TODO: Fix this\n this.#enclaveProvider.setSigner(this.signer);\n }\n\n get kwilClient(): KwilActionClient {\n return boundKwilClient(this.#kwilClient, this.kwilSigner);\n }\n\n get enclaveProvider(): BaseProvider {\n return boundEnclave(this.#enclaveProvider, this.#kwilClient, this.kwilSigner);\n }\n\n async logOut(): Promise<idOSClientIdle> {\n return finishLogOut(\n this.store,\n this.#kwilClient,\n this.kwilSigner,\n this.#enclaveProvider,\n this.blobGateway.url,\n );\n }\n\n async hasProfile(): Promise<boolean> {\n // NEAR profiles are keyed by the ed25519 public key. walletIdentifier is the account id.\n let address = this.walletIdentifier;\n if (this.walletType === \"NEAR\") {\n if (!this.walletPublicKey) throw new Error(\"NEAR wallet public key is required\");\n address = this.walletPublicKey;\n }\n return hasProfile(this.kwilClient, { address }).then((res) => {\n if (!res) throw new Error(\"has_profile returned no rows\");\n return res.has_profile;\n });\n }\n\n async createUserEncryptionProfile(\n userId: string,\n forceEncryptionPasswordStore?: EncryptionPasswordStore,\n ): Promise<PublicEncryptionProfile> {\n await exclusive(this.#kwilClient, async () => {\n assertSigner(this.#kwilClient, this.kwilSigner);\n await this.enclaveProvider.reconfigure({\n mode: \"new\",\n userId,\n walletAddress: this.walletIdentifier,\n walletPublicKey: this.walletPublicKey,\n walletType: this.walletType,\n encryptionPasswordStore: forceEncryptionPasswordStore,\n expectedUserEncryptionPublicKey: undefined,\n });\n assertSigner(this.#kwilClient, this.kwilSigner);\n });\n assertSigner(this.#kwilClient, this.kwilSigner);\n return this.enclaveProvider.ensureUserEncryptionProfile();\n }\n\n async logIn(): Promise<idOSClientLoggedIn> {\n if (!(await this.hasProfile())) throw new Error(\"User does not have a profile\");\n\n const kwilUser = await getUser(this.kwilClient);\n\n return exclusive(this.#kwilClient, async () => {\n assertSigner(this.#kwilClient, this.kwilSigner);\n await this.enclaveProvider.reconfigure({\n mode: \"existing\",\n userId: kwilUser.id,\n expectedUserEncryptionPublicKey: kwilUser.recipient_encryption_public_key,\n walletAddress: this.walletIdentifier,\n walletType: this.walletType,\n encryptionPasswordStore: kwilUser.encryption_password_store,\n walletPublicKey: this.walletPublicKey,\n });\n assertSigner(this.#kwilClient, this.kwilSigner);\n return new idOSClientLoggedIn(this, kwilUser);\n });\n }\n}\n\nfunction credentialRecipientWallet(client: {\n walletType: string;\n walletIdentifier: string;\n walletPublicKey?: string;\n}): string {\n // NEAR @caller is the ed25519 public key. walletIdentifier is the account id.\n if (client.walletType === \"NEAR\") {\n if (!client.walletPublicKey) throw new Error(\"NEAR wallet public key is required\");\n return client.walletPublicKey;\n }\n return client.walletIdentifier;\n}\n\nexport class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSigner>, \"state\"> {\n readonly state: \"logged-in\";\n readonly store: Store;\n readonly #kwilClient: KwilActionClient;\n readonly #enclaveProvider: BaseProvider;\n readonly signer: Wallet;\n readonly kwilSigner: KwilSigner;\n readonly walletIdentifier: string;\n readonly walletPublicKey: string | undefined;\n readonly walletType: WalletType;\n readonly user: idOSUser;\n readonly blobGateway: BlobGateway;\n\n constructor(idOSClientWithUserSigner: idOSClientWithUserSigner, user: idOSUser) {\n this.state = \"logged-in\";\n this.store = idOSClientWithUserSigner.store;\n this.#kwilClient = sharedKwilClient(idOSClientWithUserSigner.kwilClient);\n this.#enclaveProvider = sharedEnclave(idOSClientWithUserSigner.enclaveProvider);\n this.signer = idOSClientWithUserSigner.signer;\n this.kwilSigner = idOSClientWithUserSigner.kwilSigner;\n this.walletIdentifier = idOSClientWithUserSigner.walletIdentifier;\n this.walletPublicKey = idOSClientWithUserSigner.walletPublicKey;\n this.walletType = idOSClientWithUserSigner.walletType;\n this.user = user;\n this.blobGateway = idOSClientWithUserSigner.blobGateway;\n }\n\n get kwilClient(): KwilActionClient {\n return boundKwilClient(this.#kwilClient, this.kwilSigner);\n }\n\n get enclaveProvider(): BaseProvider {\n return boundEnclave(this.#enclaveProvider, this.#kwilClient, this.kwilSigner);\n }\n\n async logOut(): Promise<idOSClientIdle> {\n return finishLogOut(\n this.store,\n this.#kwilClient,\n this.kwilSigner,\n this.#enclaveProvider,\n this.blobGateway.url,\n );\n }\n\n async requestDWGMessage(params: idOSDelegatedWriteGrant): Promise<string> {\n return dwgMessage(this.kwilClient, params).then((res) => {\n if (!res) throw new Error(\"dwg_message returned no rows\");\n return res.message;\n });\n }\n\n async createCredential(\n publicNotes: string,\n plaintextContent: Uint8Array<ArrayBufferLike>,\n // In case of credential creation on users behalf, this would be a issuer key\n issuerSigningSecretKey?: Uint8Array,\n ): Promise<Omit<idOSCredential, \"user_id\" | \"content\" | \"inserter_type\" | \"inserter_id\">> {\n const credentialId = crypto.randomUUID();\n const preliminaryCredential: PreliminaryIDOSCredential = {\n ...(await buildPreliminaryIDOSCredential({\n publicNotes,\n plaintextContent,\n recipientEncryptionPublicKey: base64Decode(this.user.recipient_encryption_public_key),\n broaderMessageFor: (publicNotesSignature, contentUri) =>\n credentialBroaderMessage(this.kwilClient, {\n public_notes_signature: publicNotesSignature,\n content_uri: contentUri,\n recipient_wallet: credentialRecipientWallet(this),\n }).then((row) => row.message),\n issuerSigningSecretKey,\n })),\n id: credentialId,\n };\n\n const requestId = crypto.randomUUID();\n\n const payload: CreatePreliminaryCredentialInput = {\n request_id: requestId,\n credential_id: preliminaryCredential.id,\n issuer_auth_public_key: preliminaryCredential.issuerAuthPublicKey,\n encryptor_public_key: preliminaryCredential.encryptorPublicKey,\n content_uri: preliminaryCredential.contentUri,\n content_size: preliminaryCredential.contentSize,\n content_hash: hexEncodeSha256Hash(plaintextContent),\n public_notes: preliminaryCredential.publicNotes,\n public_notes_signature: preliminaryCredential.publicNotesSignature,\n broader_signature: preliminaryCredential.broaderSignature,\n };\n\n await createPreliminaryCredential(this.kwilClient, payload);\n\n await this.#uploadOwnedCredentialBlobs({\n requestId,\n credentialIds: [preliminaryCredential.id],\n original: preliminaryCredential.encryptedContent,\n });\n\n return mapPreliminaryToIDOSCredential(preliminaryCredential);\n }\n\n /**\n * A lost upload response can hide a finalized credential. The user owns it, so look it up\n * by id and read its blob back: the record alone doesn't prove the gateway stored our bytes\n * (a 2xx with a CID mismatch also lands here). Rethrow the unknown outcome unless both check\n * out, including when the credential isn't visible yet, a read fails, or the read takes\n * longer than READ_BACK_TIMEOUT_MS.\n */\n async #uploadOwnedCredentialBlobs(\n params: UploadCredentialBlobsParams & { credentialIds: [string] },\n ): Promise<void> {\n try {\n await this.blobGateway.uploadCredentialBlobs(params);\n } catch (error) {\n if (!(error instanceof BlobGatewayUploadOutcomeUnknownError)) throw error;\n\n const created = await this.getCredentialById(params.credentialIds[0]).catch(() => undefined);\n if (!created?.content_uri) throw error;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), READ_BACK_TIMEOUT_MS);\n const stored = await this.blobGateway\n .fetchBlob({\n credentialId: created.id,\n contentUri: created.content_uri,\n expectedSize: created.content_size,\n signal: controller.signal,\n })\n .catch(() => undefined)\n .finally(() => clearTimeout(timer));\n const uploaded = params.original ?? params.copy;\n if (!stored || !bytesEqual(stored, uploaded)) throw error;\n }\n }\n\n async removeCredential(id: string): Promise<{ id: string }> {\n const credential = await this.getCredentialById(id);\n invariant(credential, `\"idOSCredential\" with id ${id} not found`);\n\n const contentUri = credential.content_uri ?? null;\n if (isUkycContentUri(contentUri)) {\n throw new Error(\"ukyc:// credentials can only be removed by their MM operator's data wipe\");\n }\n\n await removeCredential(this.kwilClient, { id });\n\n if (!contentUri) {\n return { id };\n }\n\n await this.blobGateway.deleteCredentialBlob({ credentialId: id });\n return { id };\n }\n\n async getCredentialById(id: string): Promise<idOSCredential | undefined> {\n return getCredentialOwned(this.kwilClient, { id }).then((res) => res[0]);\n }\n\n async shareCredential(\n credential: SharePreliminaryCredentialInput,\n ): Promise<SharePreliminaryCredentialInput> {\n await sharePreliminaryCredential(this.kwilClient, credential);\n return credential;\n }\n\n async getAllCredentials(): Promise<idOSCredentialListItem[]> {\n return getCredentials(this.kwilClient);\n }\n\n async getAccessGrantsOwned(): Promise<idOSGrant[]> {\n return getAccessGrantsOwned(this.kwilClient);\n }\n\n async getAttributes(): Promise<idOSUserAttribute[]> {\n return getAttributes(this.kwilClient);\n }\n\n async createAttribute(attribute: AddAttributeInput): Promise<AddAttributeInput> {\n await createAttribute(this.kwilClient, attribute);\n return attribute;\n }\n\n async getCredentialContentSha256Hash(id: string): Promise<string> {\n const credential = await this.getCredentialById(id);\n\n invariant(credential, `\"idOSCredential\" with id ${id} not found`);\n const plaintext = await this.#decryptCredentialContent(credential);\n\n return hexEncodeSha256Hash(plaintext);\n }\n\n async getCredentialContent(id: string): Promise<string> {\n const credential = await this.getCredentialById(id);\n\n invariant(credential, `\"idOSCredential\" with id ${id} not found`);\n const plaintext = await this.#decryptCredentialContent(credential);\n\n return utf8Decode(plaintext);\n }\n\n async getCredentialWithEncryptedContent(id: string): Promise<idOSCredential> {\n const credential = await this.getCredentialById(id);\n invariant(credential, `\"idOSCredential\" with id ${id} not found`);\n return this.#credentialWithInlineContent(credential);\n }\n\n async getCredentialSharedContent(id: string): Promise<string> {\n const credential = await this.getCredentialShared(id);\n\n invariant(credential, `Shared credential with id ${id} not found`);\n const plaintext = await this.#decryptCredentialContent(credential);\n\n return utf8Decode(plaintext);\n }\n\n async getGrants(\n params: Partial<GetAccessGrantsGrantedInput>,\n ): Promise<{ grants: idOSGrant[]; totalCount: number }> {\n return {\n grants: await getGrants(this.kwilClient, params),\n totalCount: await this.getGrantsCount(),\n };\n }\n\n async addWallets(params: AddWalletInput[]): Promise<AddWalletInput[]> {\n await addWallets(this.kwilClient, params);\n return params;\n }\n\n async getGrantsCount(): Promise<number> {\n return getAccessGrantsGrantedCount(this.kwilClient, {\n user_id: null,\n }).then((res) => {\n if (!res) throw new Error(\"get_access_grants_granted_count returned no rows\");\n return res.count;\n });\n }\n\n async getCredentialShared(id: string): Promise<idOSCredential | undefined> {\n return getCredentialShared(this.kwilClient, { id }).then((res) => res[0]);\n }\n\n async revokeAccessGrant(id: string): Promise<{ id: string }> {\n await revokeAccessGrant(this.kwilClient, { id });\n return { id };\n }\n\n async addWalletMessage(params: AddWalletMessageInput): Promise<string> {\n const result = await requestAddWalletMessage(this.kwilClient, params);\n return result.message;\n }\n\n async addWallet(params: AddWalletInput): Promise<AddWalletInput> {\n await addWallet(this.kwilClient, params);\n\n // we don't need to add the wallet to MPC if the user is not using MPC\n if (this.user.encryption_password_store !== \"mpc\") {\n console.log(\"MPC is not enabled or the user is not using MPC\");\n return params;\n }\n\n if (!params.wallet_type) {\n throw new Error(\"Wallet type is required for MPC users\");\n }\n\n const messageToSign = await this.enclaveProvider.addAddressMessageToSign(\n params.address,\n params.public_key ?? undefined,\n params.wallet_type,\n );\n\n const signature = await this.enclaveProvider.signTypedData(\n messageToSign.domain,\n messageToSign.types,\n messageToSign.value,\n );\n\n const result = await this.enclaveProvider.addAddressToMpcSecret(\n this.user.id,\n messageToSign.value,\n signature,\n );\n\n if (result !== \"success\") {\n console.error(`Failed to add wallet to MPC: ${result}`);\n }\n\n return params;\n }\n\n async getWallets(): Promise<GetWalletsOutput[]> {\n return getWallets(this.kwilClient);\n }\n\n async removeWallet(id: string): Promise<{ id: string }> {\n const wallets = await this.getWallets();\n const wallet = wallets.find((wallet) => wallet.id === id);\n if (!wallet) {\n throw new Error(`Wallet with id ${id} not found`);\n }\n\n await removeWallet(this.kwilClient, { id });\n\n // we don't need to add the wallet to MPC if the user is not using MPC\n if (this.user.encryption_password_store !== \"mpc\") {\n console.log(\"MPC is not enabled or the user is not using MPC\");\n return { id };\n }\n\n const messageToSign = await this.enclaveProvider.removeAddressMessageToSign(\n wallet.address,\n wallet.public_key ?? undefined,\n wallet.wallet_type,\n );\n const signature = await this.enclaveProvider.signTypedData(\n messageToSign.domain,\n messageToSign.types,\n messageToSign.value,\n );\n const result = await this.enclaveProvider.removeAddressFromMpcSecret(\n wallet.user_id,\n messageToSign.value,\n signature,\n );\n if (result !== \"success\") {\n console.error(`Failed to add wallet to MPC: ${result}`);\n }\n\n return { id };\n }\n\n async removeWallets(ids: string[]): Promise<string[]> {\n for (const id of ids) {\n await this.removeWallet(id);\n }\n\n return ids;\n }\n\n async filterCredentials(requirements: {\n acceptedIssuers: {\n authPublicKey: string;\n }[];\n publicNotesFieldFilters?: {\n pick: Parameters<typeof recordFilter>[1];\n omit: Parameters<typeof recordFilter>[2];\n };\n privateFieldFilters?: {\n pick: Parameters<typeof recordFilter>[1];\n omit: Parameters<typeof recordFilter>[2];\n };\n /** @deprecated The level leaves out self-attested data. Use `claimsFilter` instead. */\n credentialLevelOrHigherFilter?: {\n userLevel: BaseLevel;\n requiredAddons: Addon[];\n };\n /** Accepted sources per claim, e.g. `{ email: [\"VERIFIED\", \"MANUAL\"] }`. See `matchClaims`. */\n claimsFilter?: ClaimRequirements;\n }): Promise<idOSCredentialListItem[]> {\n const credentials = await this.getAllCredentials();\n const originalCredentials = credentials.filter(\n (cred) => !cred.original_id && !!cred.public_notes,\n );\n\n // invariant(originalCredentials.length, \"No original credentials found\");\n let result = originalCredentials.filter((cred) => {\n return requirements.acceptedIssuers?.some(\n (issuer) => issuer.authPublicKey === cred.issuer_auth_public_key,\n );\n });\n\n const publicNotesFieldFilters = requirements.publicNotesFieldFilters;\n const credentialLevelOrHigherFilter = requirements.credentialLevelOrHigherFilter;\n const privateFieldFilters = requirements.privateFieldFilters;\n const claimsFilter = requirements.claimsFilter;\n\n if (claimsFilter) {\n result = result.filter((credential) => {\n let publicNotes: Parameters<typeof matchClaims>[1];\n\n try {\n publicNotes = JSON.parse(credential.public_notes);\n } catch (_) {\n throw new Error(`Credential ${credential.id} has non-JSON public notes.`);\n }\n\n return matchClaims(claimsFilter, publicNotes);\n });\n }\n\n if (credentialLevelOrHigherFilter) {\n result = result.filter((credential) => {\n let publicNotes: Record<string, string>;\n\n try {\n publicNotes = JSON.parse(credential.public_notes);\n } catch (_) {\n throw new Error(`Credential ${credential.id} has non-JSON public notes.`);\n }\n\n return matchLevelOrHigher(\n credentialLevelOrHigherFilter.userLevel,\n credentialLevelOrHigherFilter.requiredAddons,\n publicNotes.level,\n );\n });\n }\n\n if (\n publicNotesFieldFilters &&\n (Object.keys(publicNotesFieldFilters.pick).length > 0 ||\n Object.keys(publicNotesFieldFilters.omit).length > 0)\n ) {\n result = result.filter((credential) => {\n let publicNotes: Record<string, string>;\n\n try {\n publicNotes = JSON.parse(credential.public_notes);\n } catch (_) {\n throw new Error(`Credential ${credential.id} has non-JSON public notes.`);\n }\n\n return recordFilter(\n publicNotes,\n publicNotesFieldFilters.pick,\n publicNotesFieldFilters.omit,\n );\n });\n }\n\n // Private field filtering requires decryption and the full idOS credential content\n // it's most \"expensive\", since it requires a roundtrip to the nodes and roundtrip to enclave.\n if (\n privateFieldFilters &&\n (Object.keys(privateFieldFilters.pick).length > 0 ||\n Object.keys(privateFieldFilters.omit).length > 0)\n ) {\n const fullCredentials = await Promise.all(\n result.map((credential) => this.getCredentialById(credential.id)),\n );\n\n // Check for undefined, it will be sign of some internal error\n invariant(\n fullCredentials.every((cred) => cred !== undefined),\n \"Some credentials could not be fetched in full form for private field filtering\",\n );\n\n const matches = await this.enclaveProvider.filterCredentials(\n await Promise.all(\n fullCredentials.map((credential) => this.#credentialWithInlineContent(credential)),\n ),\n privateFieldFilters,\n );\n\n result = result.filter((credential) =>\n matches.some((matchedCredential) => matchedCredential.id === credential.id),\n );\n }\n\n return result;\n }\n\n async requestAccessGrant(\n credentialId: string,\n {\n consumerEncryptionPublicKey,\n consumerAuthPublicKey,\n lockedUntil = 0,\n }: {\n consumerEncryptionPublicKey: string;\n consumerAuthPublicKey: string;\n lockedUntil?: number;\n },\n ): Promise<SharePreliminaryCredentialInput> {\n const credential = await this.getCredentialById(credentialId);\n\n invariant(credential, `\"idOSCredential\" with id ${credentialId} not found`);\n\n const plaintextContent = await this.#decryptCredentialContent(credential);\n const contentHash = hexEncodeSha256Hash(plaintextContent);\n\n await this.enclaveProvider.ensureUserEncryptionProfile();\n\n const { content, encryptorPublicKey } = await this.enclaveProvider.encrypt(\n plaintextContent,\n base64Decode(consumerEncryptionPublicKey),\n );\n\n // User issues the shared copy: sign content_uri with an ephemeral user-side key.\n // Copy issuer_auth_public_key need not match the original credential's issuer.\n const copyId = crypto.randomUUID();\n const copyReference = await createBlobContentReference(content);\n const signedReference = await buildEphemeralSignedCredentialContentReference(\n \"\",\n copyReference.uri,\n (publicNotesSignature, contentUri) =>\n credentialBroaderMessage(this.kwilClient, {\n public_notes_signature: publicNotesSignature,\n content_uri: contentUri,\n recipient_wallet: credentialRecipientWallet(this),\n }).then((row) => row.message),\n );\n\n // Integrator-supplied. ed25519 @caller is lowercase hex; after exact grantee\n // matching, uppercase hex would store a grant the consumer cannot read. Other\n // identifier encodings (NEAR, XRPL, Stellar) are case-sensitive, so leave them.\n const granteeWalletIdentifier = /^[0-9a-fA-F]{64}$/.test(consumerAuthPublicKey)\n ? consumerAuthPublicKey.toLowerCase()\n : consumerAuthPublicKey;\n\n const preliminaryCredential: SharePreliminaryCredentialInput = {\n ...signedReference,\n request_id: crypto.randomUUID(),\n copy_id: copyId,\n original_id: credential.id,\n content_uri: copyReference.uri,\n content_size: copyReference.size,\n encryptor_public_key: base64Encode(encryptorPublicKey),\n grantee_wallet_identifier: granteeWalletIdentifier,\n locked_until: lockedUntil,\n content_hash: contentHash,\n };\n\n await this.shareCredential(preliminaryCredential);\n await this.#uploadOwnedCredentialBlobs({\n requestId: preliminaryCredential.request_id,\n credentialIds: [copyId],\n copy: content,\n });\n\n return preliminaryCredential;\n }\n\n async #credentialWithInlineContent(credential: idOSCredential): Promise<idOSCredential> {\n if (credential.content) {\n return credential;\n }\n\n return {\n ...credential,\n content: base64Encode(await this.#getCredentialEncryptedContent(credential)),\n content_uri: null,\n content_size: null,\n };\n }\n\n async #decryptCredentialContent(credential: idOSCredential): Promise<Uint8Array> {\n await this.enclaveProvider.ensureUserEncryptionProfile();\n\n return this.enclaveProvider.decrypt(\n await this.#getCredentialEncryptedContent(credential),\n base64Decode(credential.encryptor_public_key),\n );\n }\n\n async #getCredentialEncryptedContent(credential: idOSCredential): Promise<Uint8Array> {\n return resolveCredentialEncryptedContent(credential, this.blobGateway);\n }\n}\n\nexport type {\n Claim,\n ClaimRequirements,\n Claims,\n ClaimSource,\n ClaimSources,\n idOSDelegatedWriteGrant,\n DelegatedWriteGrantBaseParams,\n idOSCredential,\n idOSCredentialListItem,\n idOSGrant,\n idOSUser,\n idOSUserAttribute,\n idOSWallet,\n};\n\nexport { signNearMessage, toDelegatedWriteGrantBaseParams };\n\nexport function createIDOSClient(params: {\n nodeUrl: string;\n /**\n * Optional blob gateway base URL. Defaults to `nodeUrl`.\n * In the browser this must share KGW's session-cookie Domain\n * (typically the same host), because reads use `credentials: \"include\"`.\n */\n blobGatewayUrl?: string;\n enclaveOptions: Omit<IframeEnclave[\"options\"], \"mode\">;\n}): idOSClientConfiguration<IframeEnclave> {\n return new idOSClientConfiguration({\n nodeUrl: params.nodeUrl,\n blobGatewayUrl: params.blobGatewayUrl,\n enclaveOptions: params.enclaveOptions,\n });\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idos-network/client",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "idOS Client JavaScript SDK for browser environments",
5
5
  "homepage": "https://idos.network",
6
6
  "license": "MIT",
@@ -28,11 +28,11 @@
28
28
  "access": "public"
29
29
  },
30
30
  "dependencies": {
31
- "@idos-network/credentials": "4.0.0",
32
- "@idos-network/enclave": "3.0.2",
33
- "@idos-network/kwil-infra": "4.0.0",
31
+ "@idos-network/credentials": "4.0.1",
32
+ "@idos-network/enclave": "3.0.3",
33
+ "@idos-network/kwil-infra": "5.0.0",
34
34
  "@idos-network/kwil-js": "0.2.2",
35
- "@idos-network/utils": "3.1.0",
35
+ "@idos-network/utils": "3.2.0",
36
36
  "tiny-invariant": "^1.3.3"
37
37
  },
38
38
  "devDependencies": {
package/src/index.test.ts CHANGED
@@ -2,15 +2,10 @@
2
2
 
3
3
  import type { BaseProvider } from "@idos-network/enclave";
4
4
 
5
- import { createMmTokenAuth, KwilActionClient } from "@idos-network/kwil-infra";
5
+ import { KwilActionClient } from "@idos-network/kwil-infra";
6
6
  import { NodeKwil } from "@idos-network/kwil-js";
7
7
  import { BlobGateway, createBlobContentReference } from "@idos-network/utils/blob-gateway";
8
- import {
9
- base64Encode,
10
- base64UrlEncode,
11
- hexEncodeSha256Hash,
12
- utf8Encode,
13
- } from "@idos-network/utils/codecs";
8
+ import { base64Encode, base64UrlEncode, utf8Encode } from "@idos-network/utils/codecs";
14
9
  import { MemoryStore } from "@idos-network/utils/store";
15
10
  import { afterEach, describe, expect, it, vi } from "vitest";
16
11
 
@@ -22,18 +17,6 @@ import {
22
17
  toDelegatedWriteGrantBaseParams,
23
18
  } from "./index.js";
24
19
 
25
- const mmToken = base64UrlEncode(
26
- utf8Encode(
27
- JSON.stringify({
28
- payload: {
29
- signing_public_key: base64UrlEncode(new Uint8Array(32).fill(7)),
30
- storage_id: "storage-abc",
31
- },
32
- signature: base64UrlEncode(new Uint8Array(64).fill(9)),
33
- }),
34
- ),
35
- );
36
-
37
20
  function idleClient(): idOSClientIdle {
38
21
  const kwilClient = {
39
22
  signer: undefined,
@@ -89,44 +72,20 @@ function nodeIdleClient(): idOSClientIdle {
89
72
  );
90
73
  }
91
74
 
92
- describe("UKYC blob authorization is scoped to the signed session", () => {
93
- it("binds the MM capability when the signer is selected", async () => {
94
- const idle = idleClient();
95
-
96
- const withSigner = await idle.withUserSigner(createMmTokenAuth(mmToken));
97
-
98
- expect(withSigner.blobGateway.hasAccessToken).toBe(true);
99
- expect(idle.blobGateway.hasAccessToken).toBe(false);
100
- });
101
-
102
- it("drops the MM capability on logout", async () => {
103
- const withSigner = await idleClient().withUserSigner(createMmTokenAuth(mmToken));
104
-
105
- expect((await withSigner.logOut()).blobGateway.hasAccessToken).toBe(false);
106
- });
107
-
75
+ describe("logout", () => {
108
76
  it("resets the enclave on logout", async () => {
109
77
  const idle = idleClient();
110
78
  const reset = vi.fn(async () => {});
111
79
  idle.enclaveProvider.reset = reset;
112
- const withSigner = await idle.withUserSigner(createMmTokenAuth(mmToken));
80
+ const withSigner = await idle.withUserSigner(ed25519Signer(3) as never);
113
81
 
114
82
  await withSigner.logOut();
115
83
 
116
84
  expect(reset).toHaveBeenCalledOnce();
117
85
  });
118
86
 
119
- it("leaves a non-MM session without UKYC authorization", async () => {
120
- const idle = idleClient();
121
- const customSigner = {
122
- publicAddress: "0x1234567890123456789012345678901234567890",
123
- publicKey: base64UrlEncode(new Uint8Array(32).fill(3)),
124
- signatureType: "ed25519",
125
- walletType: "EVM",
126
- signMessage: async () => new Uint8Array(64),
127
- };
128
-
129
- const withSigner = await idle.withUserSigner(customSigner as never);
87
+ it("never sends a UKYC storage token from a user session", async () => {
88
+ const withSigner = await idleClient().withUserSigner(ed25519Signer(3) as never);
130
89
 
131
90
  expect(withSigner.blobGateway.hasAccessToken).toBe(false);
132
91
  });
@@ -393,7 +352,7 @@ describe("Node KGW-authenticated blob sessions", () => {
393
352
  vi.unstubAllGlobals();
394
353
  });
395
354
 
396
- it("sends the KGW cookie and MM AccessToken, then drops both on logout", async () => {
355
+ it("sends the KGW cookie without a storage token, then drops it on logout", async () => {
397
356
  const ciphertext = utf8Encode("ciphertext");
398
357
  const fetchFn = vi.fn<typeof fetch>(async () => {
399
358
  return new Response("ciphertext", {
@@ -402,8 +361,8 @@ describe("Node KGW-authenticated blob sessions", () => {
402
361
  });
403
362
  vi.stubGlobal("fetch", fetchFn);
404
363
 
405
- const withSigner = await nodeIdleClient().withUserSigner(createMmTokenAuth(mmToken));
406
- expect(withSigner.blobGateway.hasAccessToken).toBe(true);
364
+ const withSigner = await nodeIdleClient().withUserSigner(ed25519Signer(3) as never);
365
+ expect(withSigner.blobGateway.hasAccessToken).toBe(false);
407
366
 
408
367
  await expect(
409
368
  withSigner.blobGateway.fetchBlob({
@@ -413,7 +372,7 @@ describe("Node KGW-authenticated blob sessions", () => {
413
372
  ).resolves.toEqual(ciphertext);
414
373
 
415
374
  expect(header(fetchFn.mock.calls[0], "cookie")).toBe("kgw_session=fresh; Path=/");
416
- expect(header(fetchFn.mock.calls[0], "authorization")).toBe(`AccessToken ${mmToken}`);
375
+ expect(header(fetchFn.mock.calls[0], "authorization")).toBeNull();
417
376
 
418
377
  const idle = await withSigner.logOut();
419
378
  expect(idle.blobGateway.hasAccessToken).toBe(false);
@@ -439,7 +398,7 @@ describe("Node KGW-authenticated blob sessions", () => {
439
398
  });
440
399
  vi.stubGlobal("fetch", fetchFn);
441
400
 
442
- const withSigner = await nodeIdleClient().withUserSigner(createMmTokenAuth(mmToken));
401
+ const withSigner = await nodeIdleClient().withUserSigner(ed25519Signer(3) as never);
443
402
  vi.spyOn(withSigner.kwilClient, "call").mockResolvedValue([
444
403
  {
445
404
  id: credentialId,
@@ -466,21 +425,21 @@ describe("Node KGW-authenticated blob sessions", () => {
466
425
  expect(credential.content).toBe(base64Encode(ciphertext));
467
426
  expect(credential.content_uri).toBeNull();
468
427
  expect(header(fetchFn.mock.calls[0], "cookie")).toBe("kgw_session=fresh; Path=/");
469
- expect(header(fetchFn.mock.calls[0], "authorization")).toBe(`AccessToken ${mmToken}`);
428
+ expect(header(fetchFn.mock.calls[0], "authorization")).toBeNull();
470
429
  });
471
430
  });
472
431
 
473
432
  const NACL_BOX_ENCRYPTION_OVERHEAD_BYTES = 24 + 16; // nonce + authentication tag
474
433
  const credentialPlaintext = utf8Encode("private credential content");
475
434
 
476
- async function createCredentialForWallet(walletType: "MM" | "EVM"): Promise<{
435
+ async function createCredentialForWallet(walletType: "EVM"): Promise<{
477
436
  credential: Awaited<ReturnType<idOSClientLoggedIn["createCredential"]>>;
478
437
  preliminaryInput: Record<string, unknown> | undefined;
479
438
  uploadedBytes: Uint8Array | undefined;
480
439
  }> {
481
440
  let preliminaryInput: Record<string, unknown> | undefined;
482
441
  let uploadedBytes: Uint8Array | undefined;
483
- const kwilSigner = walletType === "MM" ? createMmTokenAuth(mmToken) : {};
442
+ const kwilSigner = {};
484
443
  const kwilClient = {
485
444
  signer: kwilSigner,
486
445
  call: async () => [{ message: "credential-message" }],
@@ -490,7 +449,6 @@ async function createCredentialForWallet(walletType: "MM" | "EVM"): Promise<{
490
449
  } as unknown as KwilActionClient;
491
450
  const blobGateway = new BlobGateway({
492
451
  url: "https://blob.example",
493
- accessToken: walletType === "MM" ? mmToken : undefined,
494
452
  fetchFn: async (_input, init) => {
495
453
  const body = init?.body;
496
454
  if (!(body instanceof FormData)) throw new Error("Expected multipart upload");
@@ -530,19 +488,6 @@ async function createCredentialForWallet(walletType: "MM" | "EVM"): Promise<{
530
488
  }
531
489
 
532
490
  describe("credential blob storage", () => {
533
- it("creates MM credentials with ukyc:// and the encrypted byte size", async () => {
534
- const { credential, preliminaryInput, uploadedBytes } = await createCredentialForWallet("MM");
535
-
536
- expect(credential.content_uri).toBe(
537
- `ukyc://storage-abc/blobs/${hexEncodeSha256Hash(uploadedBytes ?? new Uint8Array())}`,
538
- );
539
- expect(preliminaryInput?.content_uri).toBe(credential.content_uri);
540
- expect(preliminaryInput?.content_size).toBe(
541
- credentialPlaintext.byteLength + NACL_BOX_ENCRYPTION_OVERHEAD_BYTES,
542
- );
543
- expect(uploadedBytes?.byteLength).toBe(preliminaryInput?.content_size);
544
- });
545
-
546
491
  it("creates non-MM credentials through the IPFS CID-validation flow", async () => {
547
492
  const { credential, preliminaryInput, uploadedBytes } = await createCredentialForWallet("EVM");
548
493
 
package/src/index.ts CHANGED
@@ -25,9 +25,7 @@ import {
25
25
  createKgwAuthenticatedBlobGateway,
26
26
  createNodeKwilClient,
27
27
  createWebKwilClient,
28
- isMmTokenAuth,
29
28
  type KwilActionClient,
30
- mmTokenStorageId,
31
29
  signNearMessage,
32
30
  type Wallet,
33
31
  } from "@idos-network/kwil-infra";
@@ -76,8 +74,7 @@ import {
76
74
  BlobGateway,
77
75
  BlobGatewayUploadOutcomeUnknownError,
78
76
  createBlobContentReference,
79
- createUkycContentReference,
80
- requireAccessTokenForUkycContent,
77
+ isUkycContentUri,
81
78
  resolveCredentialEncryptedContent,
82
79
  type UploadCredentialBlobsParams,
83
80
  } from "@idos-network/utils/blob-gateway";
@@ -128,19 +125,7 @@ function blobGatewayForSigner(idle: idOSClientIdle, kwilSigner: KwilSigner): Blo
128
125
  });
129
126
  }
130
127
 
131
- return isMmTokenAuth(kwilSigner)
132
- ? idle.blobGateway.withAccessToken(kwilSigner.accessToken)
133
- : idle.blobGateway;
134
- }
135
-
136
- function ukycStorageIdForWallet(
137
- walletType: WalletType,
138
- kwilSigner: KwilSigner,
139
- ): string | undefined {
140
- if (walletType !== "MM") {
141
- return undefined;
142
- }
143
- return mmTokenStorageId(kwilSigner);
128
+ return idle.blobGateway;
144
129
  }
145
130
 
146
131
  // Deadline for reading a blob back after an unknown upload outcome. A slower read leaves the
@@ -653,14 +638,9 @@ export class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSig
653
638
  recipient_wallet: credentialRecipientWallet(this),
654
639
  }).then((row) => row.message),
655
640
  issuerSigningSecretKey,
656
- ukycStorageId: ukycStorageIdForWallet(this.walletType, this.kwilSigner),
657
641
  })),
658
642
  id: credentialId,
659
643
  };
660
- requireAccessTokenForUkycContent(
661
- preliminaryCredential.contentUri,
662
- this.blobGateway.hasAccessToken,
663
- );
664
644
 
665
645
  const requestId = crypto.randomUUID();
666
646
 
@@ -727,7 +707,9 @@ export class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSig
727
707
  invariant(credential, `"idOSCredential" with id ${id} not found`);
728
708
 
729
709
  const contentUri = credential.content_uri ?? null;
730
- requireAccessTokenForUkycContent(contentUri, this.blobGateway.hasAccessToken);
710
+ if (isUkycContentUri(contentUri)) {
711
+ throw new Error("ukyc:// credentials can only be removed by their MM operator's data wipe");
712
+ }
731
713
 
732
714
  await removeCredential(this.kwilClient, { id });
733
715
 
@@ -1076,11 +1058,7 @@ export class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSig
1076
1058
  // User issues the shared copy: sign content_uri with an ephemeral user-side key.
1077
1059
  // Copy issuer_auth_public_key need not match the original credential's issuer.
1078
1060
  const copyId = crypto.randomUUID();
1079
- const ukycStorageId = ukycStorageIdForWallet(this.walletType, this.kwilSigner);
1080
- const copyReference = ukycStorageId
1081
- ? createUkycContentReference(ukycStorageId, content)
1082
- : await createBlobContentReference(content);
1083
- requireAccessTokenForUkycContent(copyReference.uri, this.blobGateway.hasAccessToken);
1061
+ const copyReference = await createBlobContentReference(content);
1084
1062
  const signedReference = await buildEphemeralSignedCredentialContentReference(
1085
1063
  "",
1086
1064
  copyReference.uri,
@@ -1094,7 +1072,7 @@ export class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSig
1094
1072
 
1095
1073
  // Integrator-supplied. ed25519 @caller is lowercase hex; after exact grantee
1096
1074
  // matching, uppercase hex would store a grant the consumer cannot read. Other
1097
- // identifier encodings (NEAR, XRPL, Stellar, MM) are case-sensitive, so leave them.
1075
+ // identifier encodings (NEAR, XRPL, Stellar) are case-sensitive, so leave them.
1098
1076
  const granteeWalletIdentifier = /^[0-9a-fA-F]{64}$/.test(consumerAuthPublicKey)
1099
1077
  ? consumerAuthPublicKey.toLowerCase()
1100
1078
  : consumerAuthPublicKey;