@idos-network/client 3.1.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,mmTokenCredentialContentUri 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 te,dwgMessage as g,getAccessGrantsGrantedCount as _,getAccessGrantsOwned as ne,getAttributes as re,getCredentialOwned as ie,getCredentialShared as ae,getCredentials as oe,getGrants as v,getUser as se,getWallets as ce,hasProfile as y,removeCredential as b,removeWallet as le,revokeAccessGrant as x,sharePreliminaryCredential as ue,toDelegatedWriteGrantBaseParams as de}from"@idos-network/kwil-infra/actions";import{NodeKwil as fe}from"@idos-network/kwil-js";import{BlobGateway as S,createBlobContentReference as pe,requireAccessTokenForUkycContent as C,resolveCredentialEncryptedContent as me}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 he,MemoryStore as ge}from"@idos-network/utils/store";import O from"tiny-invariant";import{BaseProvider as _e}from"@idos-network/enclave";var k=class extends _e{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 fe}function M(e){return A()?new S({url:e,fetchFn:(e,t)=>fetch(e,{...t,credentials:`include`})}):new S({url:e})}function N(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 P(e,t,n){if(e===`MM`)return d(t,n)}const F="This idOS client is stale: another signer was set or it was logged out. Use the client returned by the latest `withUserSigner()`.",I=new WeakMap,L=new WeakMap,R=new WeakMap,z=new WeakMap,B=new WeakMap,V=new WeakSet;function H(e){return I.get(e)??e}function U(e,t){if(e.signer!==t)throw Error(F)}function W(e,t){let n=H(e),r=t?L.get(n)?.get(t):void 0;if(r)return r;let i=()=>U(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(I.set(a,n),t){let e=L.get(n)??new WeakMap;e.set(t,a),L.set(n,e)}return a}function G(e){return e&&R.get(e)||e}function K(e,t,n){let r=G(e),i=n?z.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)=>(U(t,n),i.apply(e,r)):(U(t,n),i)}});if(R.set(a,r),n){let e=z.get(r)??new WeakMap;e.set(n,a),z.set(r,e)}return a}function q(e,t){let n=H(e),r=(B.get(n)??Promise.resolve()).then(t,t);return B.set(n,r.then(()=>void 0,()=>void 0)),r}function J(){return new Proxy({},{get(e,t){if(t!==`signer`&&t!==`then`&&typeof t!=`symbol`){if(t===`client`)throw Error(F);return t===`setSigner`?()=>{throw Error(F)}:async()=>{throw Error(F)}}}})}function ve(e,t){return new Z(e,J(),J(),M(t))}function Y(e,t,n,r,i){let a=H(t);return q(a,async()=>{let t=a.signer;return t!==void 0&&t!==n||(t===n&&(a.setSigner(void 0),V.add(a)),V.has(a)&&(await r.reset(),V.delete(a)),a.signer!==void 0&&a.signer!==n)?ve(e,i):new Z(e,a,r,M(i))})}var X=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 he:new ge),this.enclaveProvider=e.enclaveProvider?new e.enclaveProvider({...e.enclaveOptions,store:this.store}):new k(e.enclaveOptions)}async createClient(){return Z.fromConfig(this)}},Z=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=>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 q(this.kwilClient,async()=>(this.kwilClient.setSigner(n),new Q(this,t,n,r,i,a,N(this,n))))}async logOut(){return this}},Q=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 W(this.#e,this.kwilSigner)}get enclaveProvider(){return K(this.#t,this.#e,this.kwilSigner)}async logOut(){return Y(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=>e.has_profile)}async createUserEncryptionProfile(e,t){return await q(this.#e,async()=>{U(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}),U(this.#e,this.kwilSigner)}),U(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 q(this.#e,async()=>(U(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}),U(this.#e,this.kwilSigner),new $(this,e)))}},$=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=H(e.kwilClient),this.#t=G(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 W(this.#e,this.kwilSigner)}get enclaveProvider(){return K(this.#t,this.#e,this.kwilSigner)}async logOut(){return Y(this.store,this.#e,this.kwilSigner,this.#t,this.blobGateway.url)}async requestDWGMessage(e){return g(this.kwilClient,e).then(e=>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),issuerSigningSecretKey:i,contentUri:P(this.walletType,this.kwilSigner,a)}),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 te(this.kwilClient,c),await this.blobGateway.uploadCredentialBlobs({requestId:s,original:o.encryptedContent}),n(o)}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 ie(this.kwilClient,{id:e}).then(e=>e[0])}async shareCredential(e){return await ue(this.kwilClient,e),e}async getAllCredentials(){return oe(this.kwilClient)}async getAccessGrantsOwned(){return ne(this.kwilClient)}async getAttributes(){return re(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.#r(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.#r(t);return D(n)}async getCredentialWithEncryptedContent(e){let t=await this.getCredentialById(e);return O(t,`"idOSCredential" with id ${e} not found`),this.#n(t)}async getCredentialSharedContent(e){let t=await this.getCredentialShared(e);O(t,`Shared credential with id ${e} not found`);let n=await this.#r(t);return D(n)}async getGrants(e){return{grants:await v(this.kwilClient,e),totalCount:await this.getGrantsCount()}}async addWallets(e){return await ee(this.kwilClient,e),e}async getGrantsCount(){return _(this.kwilClient,{user_id:null}).then(e=>e.count)}async getCredentialShared(e){return ae(this.kwilClient,{id:e}).then(e=>e[0])}async revokeAccessGrant(e){return await x(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 ce(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 le(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.#n(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.#r(a),s=E(o);await this.enclaveProvider.ensureUserEncryptionProfile();let{content:c,encryptorPublicKey:l}=await this.enclaveProvider.encrypt(o,w(n)),u=crypto.randomUUID(),d=P(this.walletType,this.kwilSigner,u);C(d,this.blobGateway.hasAccessToken);let f=d?{uri:d,size:c.byteLength}:await pe(c),p=e(``,f.uri),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.blobGateway.uploadCredentialBlobs({requestId:h.request_id,copy:c}),h}async#n(e){return e.content?e:{...e,content:T(await this.#i(e)),content_uri:null,content_size:null}}async#r(e){return await this.enclaveProvider.ensureUserEncryptionProfile(),this.enclaveProvider.decrypt(await this.#i(e),w(e.encryptor_public_key))}async#i(e){return me(e,this.blobGateway)}};function ye(e){return new X({nodeUrl:e.nodeUrl,blobGatewayUrl:e.blobGatewayUrl,enclaveOptions:e.enclaveOptions})}export{k as IframeEnclave,ye as createIDOSClient,X as idOSClientConfiguration,Z as idOSClientIdle,$ as idOSClientLoggedIn,Q as idOSClientWithUserSigner,f as signNearMessage,de 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 mmTokenCredentialContentUri,\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 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 createBlobContentReference,\n requireAccessTokenForUkycContent,\n resolveCredentialEncryptedContent,\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 contentUriForWallet(\n walletType: WalletType,\n kwilSigner: KwilSigner,\n credentialId: string,\n): string | undefined {\n if (walletType !== \"MM\") {\n return undefined;\n }\n return mmTokenCredentialContentUri(kwilSigner, credentialId);\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) => res.has_profile);\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((x) => x.has_profile);\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\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) => res.message);\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 issuerSigningSecretKey,\n contentUri: contentUriForWallet(this.walletType, this.kwilSigner, credentialId),\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.blobGateway.uploadCredentialBlobs({\n requestId,\n original: preliminaryCredential.encryptedContent,\n });\n\n return mapPreliminaryToIDOSCredential(preliminaryCredential);\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) => res.count);\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 ukycContentUri = contentUriForWallet(this.walletType, this.kwilSigner, copyId);\n requireAccessTokenForUkycContent(ukycContentUri, this.blobGateway.hasAccessToken);\n const copyReference = ukycContentUri\n ? { uri: ukycContentUri, size: content.byteLength }\n : await createBlobContentReference(content);\n const signedReference = buildEphemeralSignedCredentialContentReference(\"\", copyReference.uri);\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.blobGateway.uploadCredentialBlobs({\n requestId: preliminaryCredential.request_id,\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": "3.1.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": "3.1.0",
32
- "@idos-network/enclave": "3.0.1",
33
- "@idos-network/kwil-infra": "3.0.1",
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.0.1",
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,7 +2,7 @@
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
8
  import { base64Encode, base64UrlEncode, utf8Encode } from "@idos-network/utils/codecs";
@@ -17,18 +17,6 @@ import {
17
17
  toDelegatedWriteGrantBaseParams,
18
18
  } from "./index.js";
19
19
 
20
- const mmToken = base64UrlEncode(
21
- utf8Encode(
22
- JSON.stringify({
23
- payload: {
24
- signing_public_key: base64UrlEncode(new Uint8Array(32).fill(7)),
25
- storage_id: "storage-abc",
26
- },
27
- signature: base64UrlEncode(new Uint8Array(64).fill(9)),
28
- }),
29
- ),
30
- );
31
-
32
20
  function idleClient(): idOSClientIdle {
33
21
  const kwilClient = {
34
22
  signer: undefined,
@@ -84,44 +72,20 @@ function nodeIdleClient(): idOSClientIdle {
84
72
  );
85
73
  }
86
74
 
87
- describe("UKYC blob authorization is scoped to the signed session", () => {
88
- it("binds the MM capability when the signer is selected", async () => {
89
- const idle = idleClient();
90
-
91
- const withSigner = await idle.withUserSigner(createMmTokenAuth(mmToken));
92
-
93
- expect(withSigner.blobGateway.hasAccessToken).toBe(true);
94
- expect(idle.blobGateway.hasAccessToken).toBe(false);
95
- });
96
-
97
- it("drops the MM capability on logout", async () => {
98
- const withSigner = await idleClient().withUserSigner(createMmTokenAuth(mmToken));
99
-
100
- expect((await withSigner.logOut()).blobGateway.hasAccessToken).toBe(false);
101
- });
102
-
75
+ describe("logout", () => {
103
76
  it("resets the enclave on logout", async () => {
104
77
  const idle = idleClient();
105
78
  const reset = vi.fn(async () => {});
106
79
  idle.enclaveProvider.reset = reset;
107
- const withSigner = await idle.withUserSigner(createMmTokenAuth(mmToken));
80
+ const withSigner = await idle.withUserSigner(ed25519Signer(3) as never);
108
81
 
109
82
  await withSigner.logOut();
110
83
 
111
84
  expect(reset).toHaveBeenCalledOnce();
112
85
  });
113
86
 
114
- it("leaves a non-MM session without UKYC authorization", async () => {
115
- const idle = idleClient();
116
- const customSigner = {
117
- publicAddress: "0x1234567890123456789012345678901234567890",
118
- publicKey: base64UrlEncode(new Uint8Array(32).fill(3)),
119
- signatureType: "ed25519",
120
- walletType: "EVM",
121
- signMessage: async () => new Uint8Array(64),
122
- };
123
-
124
- 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);
125
89
 
126
90
  expect(withSigner.blobGateway.hasAccessToken).toBe(false);
127
91
  });
@@ -388,7 +352,7 @@ describe("Node KGW-authenticated blob sessions", () => {
388
352
  vi.unstubAllGlobals();
389
353
  });
390
354
 
391
- 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 () => {
392
356
  const ciphertext = utf8Encode("ciphertext");
393
357
  const fetchFn = vi.fn<typeof fetch>(async () => {
394
358
  return new Response("ciphertext", {
@@ -397,8 +361,8 @@ describe("Node KGW-authenticated blob sessions", () => {
397
361
  });
398
362
  vi.stubGlobal("fetch", fetchFn);
399
363
 
400
- const withSigner = await nodeIdleClient().withUserSigner(createMmTokenAuth(mmToken));
401
- expect(withSigner.blobGateway.hasAccessToken).toBe(true);
364
+ const withSigner = await nodeIdleClient().withUserSigner(ed25519Signer(3) as never);
365
+ expect(withSigner.blobGateway.hasAccessToken).toBe(false);
402
366
 
403
367
  await expect(
404
368
  withSigner.blobGateway.fetchBlob({
@@ -408,7 +372,7 @@ describe("Node KGW-authenticated blob sessions", () => {
408
372
  ).resolves.toEqual(ciphertext);
409
373
 
410
374
  expect(header(fetchFn.mock.calls[0], "cookie")).toBe("kgw_session=fresh; Path=/");
411
- expect(header(fetchFn.mock.calls[0], "authorization")).toBe(`AccessToken ${mmToken}`);
375
+ expect(header(fetchFn.mock.calls[0], "authorization")).toBeNull();
412
376
 
413
377
  const idle = await withSigner.logOut();
414
378
  expect(idle.blobGateway.hasAccessToken).toBe(false);
@@ -434,7 +398,7 @@ describe("Node KGW-authenticated blob sessions", () => {
434
398
  });
435
399
  vi.stubGlobal("fetch", fetchFn);
436
400
 
437
- const withSigner = await nodeIdleClient().withUserSigner(createMmTokenAuth(mmToken));
401
+ const withSigner = await nodeIdleClient().withUserSigner(ed25519Signer(3) as never);
438
402
  vi.spyOn(withSigner.kwilClient, "call").mockResolvedValue([
439
403
  {
440
404
  id: credentialId,
@@ -461,30 +425,30 @@ describe("Node KGW-authenticated blob sessions", () => {
461
425
  expect(credential.content).toBe(base64Encode(ciphertext));
462
426
  expect(credential.content_uri).toBeNull();
463
427
  expect(header(fetchFn.mock.calls[0], "cookie")).toBe("kgw_session=fresh; Path=/");
464
- expect(header(fetchFn.mock.calls[0], "authorization")).toBe(`AccessToken ${mmToken}`);
428
+ expect(header(fetchFn.mock.calls[0], "authorization")).toBeNull();
465
429
  });
466
430
  });
467
431
 
468
432
  const NACL_BOX_ENCRYPTION_OVERHEAD_BYTES = 24 + 16; // nonce + authentication tag
469
433
  const credentialPlaintext = utf8Encode("private credential content");
470
434
 
471
- async function createCredentialForWallet(walletType: "MM" | "EVM"): Promise<{
435
+ async function createCredentialForWallet(walletType: "EVM"): Promise<{
472
436
  credential: Awaited<ReturnType<idOSClientLoggedIn["createCredential"]>>;
473
437
  preliminaryInput: Record<string, unknown> | undefined;
474
438
  uploadedBytes: Uint8Array | undefined;
475
439
  }> {
476
440
  let preliminaryInput: Record<string, unknown> | undefined;
477
441
  let uploadedBytes: Uint8Array | undefined;
478
- const kwilSigner = walletType === "MM" ? createMmTokenAuth(mmToken) : {};
442
+ const kwilSigner = {};
479
443
  const kwilClient = {
480
444
  signer: kwilSigner,
445
+ call: async () => [{ message: "credential-message" }],
481
446
  execute: async ({ inputs }: { inputs: Record<string, unknown> }) => {
482
447
  preliminaryInput = inputs;
483
448
  },
484
449
  } as unknown as KwilActionClient;
485
450
  const blobGateway = new BlobGateway({
486
451
  url: "https://blob.example",
487
- accessToken: walletType === "MM" ? mmToken : undefined,
488
452
  fetchFn: async (_input, init) => {
489
453
  const body = init?.body;
490
454
  if (!(body instanceof FormData)) throw new Error("Expected multipart upload");
@@ -524,17 +488,6 @@ async function createCredentialForWallet(walletType: "MM" | "EVM"): Promise<{
524
488
  }
525
489
 
526
490
  describe("credential blob storage", () => {
527
- it("creates MM credentials with ukyc:// and the encrypted byte size", async () => {
528
- const { credential, preliminaryInput, uploadedBytes } = await createCredentialForWallet("MM");
529
-
530
- expect(credential.content_uri).toMatch(/^ukyc:\/\/storage-abc\/blobs\//);
531
- expect(preliminaryInput?.content_uri).toBe(credential.content_uri);
532
- expect(preliminaryInput?.content_size).toBe(
533
- credentialPlaintext.byteLength + NACL_BOX_ENCRYPTION_OVERHEAD_BYTES,
534
- );
535
- expect(uploadedBytes?.byteLength).toBe(preliminaryInput?.content_size);
536
- });
537
-
538
491
  it("creates non-MM credentials through the IPFS CID-validation flow", async () => {
539
492
  const { credential, preliminaryInput, uploadedBytes } = await createCredentialForWallet("EVM");
540
493
 
@@ -546,6 +499,144 @@ describe("credential blob storage", () => {
546
499
  expect(uploadedBytes?.byteLength).toBe(preliminaryInput?.content_size);
547
500
  });
548
501
 
502
+ describe("when the upload outcome is unknown", () => {
503
+ type StoredRecord = { content_uri: string; content_size: number; blob: Uint8Array };
504
+
505
+ afterEach(() => {
506
+ vi.useRealTimers();
507
+ });
508
+
509
+ // The upload POST loses its response; blob GETs serve whatever the record says is stored.
510
+ function clientWithLostUpload(
511
+ lookup: (id: string, uploaded: Uint8Array) => Promise<StoredRecord | undefined>,
512
+ onRead?: (signal: AbortSignal | undefined) => Promise<Response>,
513
+ ): idOSClientLoggedIn {
514
+ let uploaded = new Uint8Array();
515
+ let stored: StoredRecord | undefined;
516
+ const kwilSigner = {};
517
+ const kwilClient = {
518
+ signer: kwilSigner,
519
+ execute: async () => undefined,
520
+ call: async ({ name, inputs }: { name: string; inputs: { id: string } }) => {
521
+ // Other view calls made while building the credential (e.g. a message to sign).
522
+ if (name !== "get_credential_owned") return [{ message: "credential-message" }];
523
+ stored = await lookup(inputs.id, uploaded);
524
+ return stored ? [{ id: inputs.id, ...stored }] : [];
525
+ },
526
+ } as unknown as KwilActionClient;
527
+ const blobGateway = new BlobGateway({
528
+ url: "https://blob.example",
529
+ uploadRetries: 0,
530
+ fetchFn: async (_input, init) => {
531
+ if (init?.method === "POST") {
532
+ const original = (init.body as FormData).get("original") as Blob;
533
+ uploaded = new Uint8Array(await original.arrayBuffer());
534
+ throw new TypeError("fetch failed");
535
+ }
536
+ if (!stored) throw new Error("unexpected blob read");
537
+ if (onRead) return onRead(init?.signal ?? undefined);
538
+ return new Response(stored.blob.slice());
539
+ },
540
+ });
541
+ const withSigner = {
542
+ store: new MemoryStore(),
543
+ kwilClient,
544
+ enclaveProvider: {},
545
+ signer: {},
546
+ kwilSigner,
547
+ walletIdentifier: "wallet",
548
+ walletPublicKey: undefined,
549
+ walletType: "EVM",
550
+ blobGateway,
551
+ } as unknown as idOSClientWithUserSigner;
552
+ return new idOSClientLoggedIn(withSigner, {
553
+ id: crypto.randomUUID(),
554
+ recipient_encryption_public_key: base64Encode(new Uint8Array(32).fill(7)),
555
+ encryption_password_store: "user",
556
+ });
557
+ }
558
+
559
+ it("returns the credential when it exists and its blob matches the upload", async () => {
560
+ const lookedUp: string[] = [];
561
+ const client = clientWithLostUpload(async (id, uploaded) => {
562
+ lookedUp.push(id);
563
+ const { uri } = await createBlobContentReference(uploaded);
564
+ return { content_uri: uri, content_size: uploaded.byteLength, blob: uploaded };
565
+ });
566
+
567
+ const credential = await client.createCredential("public notes", credentialPlaintext);
568
+
569
+ expect(lookedUp).toEqual([credential.id]);
570
+ });
571
+
572
+ it("rethrows when the stored blob differs from the upload", async () => {
573
+ const client = clientWithLostUpload(async (_id, uploaded) => {
574
+ const tampered = uploaded.slice();
575
+ tampered[0] ^= 1;
576
+ // A non-ipfs URI skips the CID check, so this exercises the byte comparison.
577
+ return {
578
+ content_uri: "ukyc://storage-abc/blobs/credential",
579
+ content_size: tampered.byteLength,
580
+ blob: tampered,
581
+ };
582
+ });
583
+
584
+ await expect(
585
+ client.createCredential("public notes", credentialPlaintext),
586
+ ).rejects.toMatchObject({ name: "BlobGatewayUploadOutcomeUnknownError" });
587
+ });
588
+
589
+ it("gives up on a stalled read-back after the deadline", async () => {
590
+ vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout"] });
591
+ let readStarted!: () => void;
592
+ const started = new Promise<void>((resolve) => {
593
+ readStarted = resolve;
594
+ });
595
+ const client = clientWithLostUpload(
596
+ async (_id, uploaded) => {
597
+ const { uri } = await createBlobContentReference(uploaded);
598
+ return { content_uri: uri, content_size: uploaded.byteLength, blob: uploaded };
599
+ },
600
+ (signal) => {
601
+ readStarted();
602
+ // Never answers; only the abort signal can end it.
603
+ return new Promise((_resolve, reject) => {
604
+ signal?.addEventListener("abort", () => reject(signal.reason));
605
+ });
606
+ },
607
+ );
608
+
609
+ const creation = client.createCredential("public notes", credentialPlaintext);
610
+ const outcome = expect(creation).rejects.toMatchObject({
611
+ name: "BlobGatewayUploadOutcomeUnknownError",
612
+ });
613
+ await started;
614
+ await vi.advanceTimersByTimeAsync(60_000);
615
+ await outcome;
616
+ });
617
+
618
+ it("rethrows with the credential id when the credential isn't there", async () => {
619
+ const client = clientWithLostUpload(async () => undefined);
620
+
621
+ await expect(
622
+ client.createCredential("public notes", credentialPlaintext),
623
+ ).rejects.toMatchObject({
624
+ name: "BlobGatewayUploadOutcomeUnknownError",
625
+ credentialIds: [expect.any(String)],
626
+ });
627
+ });
628
+
629
+ it("rethrows the unknown outcome when the lookup itself fails", async () => {
630
+ const client = clientWithLostUpload(async () => {
631
+ throw new Error("node unavailable");
632
+ });
633
+
634
+ await expect(
635
+ client.createCredential("public notes", credentialPlaintext),
636
+ ).rejects.toMatchObject({ name: "BlobGatewayUploadOutcomeUnknownError" });
637
+ });
638
+ });
639
+
549
640
  it("returns the dwg message string and maps params via toDelegatedWriteGrantBaseParams", async () => {
550
641
  const callAction = vi.fn(async () => [{ message: "mock-dwg-message" }]);
551
642
  const kwilClient = {
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
- mmTokenCredentialContentUri,
31
29
  signNearMessage,
32
30
  type Wallet,
33
31
  } from "@idos-network/kwil-infra";
@@ -40,6 +38,7 @@ import {
40
38
  addWallets,
41
39
  addAttribute as createAttribute,
42
40
  createPreliminaryCredential,
41
+ credentialBroaderMessage,
43
42
  type CreatePreliminaryCredentialInput,
44
43
  dwgMessage,
45
44
  type GetAccessGrantsGrantedInput,
@@ -73,9 +72,11 @@ import {
73
72
  import { NodeKwil, type KwilSigner } from "@idos-network/kwil-js";
74
73
  import {
75
74
  BlobGateway,
75
+ BlobGatewayUploadOutcomeUnknownError,
76
76
  createBlobContentReference,
77
- requireAccessTokenForUkycContent,
77
+ isUkycContentUri,
78
78
  resolveCredentialEncryptedContent,
79
+ type UploadCredentialBlobsParams,
79
80
  } from "@idos-network/utils/blob-gateway";
80
81
  import {
81
82
  base64Decode,
@@ -124,20 +125,15 @@ function blobGatewayForSigner(idle: idOSClientIdle, kwilSigner: KwilSigner): Blo
124
125
  });
125
126
  }
126
127
 
127
- return isMmTokenAuth(kwilSigner)
128
- ? idle.blobGateway.withAccessToken(kwilSigner.accessToken)
129
- : idle.blobGateway;
128
+ return idle.blobGateway;
130
129
  }
131
130
 
132
- function contentUriForWallet(
133
- walletType: WalletType,
134
- kwilSigner: KwilSigner,
135
- credentialId: string,
136
- ): string | undefined {
137
- if (walletType !== "MM") {
138
- return undefined;
139
- }
140
- return mmTokenCredentialContentUri(kwilSigner, credentialId);
131
+ // Deadline for reading a blob back after an unknown upload outcome. A slower read leaves the
132
+ // outcome unknown, which callers already have to handle, instead of hanging the call.
133
+ const READ_BACK_TIMEOUT_MS = 60_000;
134
+
135
+ function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {
136
+ return a.byteLength === b.byteLength && a.every((byte, index) => byte === b[index]);
141
137
  }
142
138
 
143
139
  const STALE_CLIENT =
@@ -406,7 +402,10 @@ export class idOSClientIdle {
406
402
  }
407
403
 
408
404
  async addressHasProfile(address: string): Promise<boolean> {
409
- return hasProfile(this.kwilClient, { address }).then((res) => res.has_profile);
405
+ return hasProfile(this.kwilClient, { address }).then((res) => {
406
+ if (!res) throw new Error("has_profile returned no rows");
407
+ return res.has_profile;
408
+ });
410
409
  }
411
410
 
412
411
  async withUserSigner(_signer: Wallet): Promise<idOSClientWithUserSigner> {
@@ -506,7 +505,10 @@ export class idOSClientWithUserSigner implements Omit<Properties<idOSClientIdle>
506
505
  if (!this.walletPublicKey) throw new Error("NEAR wallet public key is required");
507
506
  address = this.walletPublicKey;
508
507
  }
509
- return hasProfile(this.kwilClient, { address }).then((x) => x.has_profile);
508
+ return hasProfile(this.kwilClient, { address }).then((res) => {
509
+ if (!res) throw new Error("has_profile returned no rows");
510
+ return res.has_profile;
511
+ });
510
512
  }
511
513
 
512
514
  async createUserEncryptionProfile(
@@ -552,6 +554,19 @@ export class idOSClientWithUserSigner implements Omit<Properties<idOSClientIdle>
552
554
  }
553
555
  }
554
556
 
557
+ function credentialRecipientWallet(client: {
558
+ walletType: string;
559
+ walletIdentifier: string;
560
+ walletPublicKey?: string;
561
+ }): string {
562
+ // NEAR @caller is the ed25519 public key. walletIdentifier is the account id.
563
+ if (client.walletType === "NEAR") {
564
+ if (!client.walletPublicKey) throw new Error("NEAR wallet public key is required");
565
+ return client.walletPublicKey;
566
+ }
567
+ return client.walletIdentifier;
568
+ }
569
+
555
570
  export class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSigner>, "state"> {
556
571
  readonly state: "logged-in";
557
572
  readonly store: Store;
@@ -598,7 +613,10 @@ export class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSig
598
613
  }
599
614
 
600
615
  async requestDWGMessage(params: idOSDelegatedWriteGrant): Promise<string> {
601
- return dwgMessage(this.kwilClient, params).then((res) => res.message);
616
+ return dwgMessage(this.kwilClient, params).then((res) => {
617
+ if (!res) throw new Error("dwg_message returned no rows");
618
+ return res.message;
619
+ });
602
620
  }
603
621
 
604
622
  async createCredential(
@@ -613,15 +631,16 @@ export class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSig
613
631
  publicNotes,
614
632
  plaintextContent,
615
633
  recipientEncryptionPublicKey: base64Decode(this.user.recipient_encryption_public_key),
634
+ broaderMessageFor: (publicNotesSignature, contentUri) =>
635
+ credentialBroaderMessage(this.kwilClient, {
636
+ public_notes_signature: publicNotesSignature,
637
+ content_uri: contentUri,
638
+ recipient_wallet: credentialRecipientWallet(this),
639
+ }).then((row) => row.message),
616
640
  issuerSigningSecretKey,
617
- contentUri: contentUriForWallet(this.walletType, this.kwilSigner, credentialId),
618
641
  })),
619
642
  id: credentialId,
620
643
  };
621
- requireAccessTokenForUkycContent(
622
- preliminaryCredential.contentUri,
623
- this.blobGateway.hasAccessToken,
624
- );
625
644
 
626
645
  const requestId = crypto.randomUUID();
627
646
 
@@ -640,20 +659,57 @@ export class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSig
640
659
 
641
660
  await createPreliminaryCredential(this.kwilClient, payload);
642
661
 
643
- await this.blobGateway.uploadCredentialBlobs({
662
+ await this.#uploadOwnedCredentialBlobs({
644
663
  requestId,
664
+ credentialIds: [preliminaryCredential.id],
645
665
  original: preliminaryCredential.encryptedContent,
646
666
  });
647
667
 
648
668
  return mapPreliminaryToIDOSCredential(preliminaryCredential);
649
669
  }
650
670
 
671
+ /**
672
+ * A lost upload response can hide a finalized credential. The user owns it, so look it up
673
+ * by id and read its blob back: the record alone doesn't prove the gateway stored our bytes
674
+ * (a 2xx with a CID mismatch also lands here). Rethrow the unknown outcome unless both check
675
+ * out, including when the credential isn't visible yet, a read fails, or the read takes
676
+ * longer than READ_BACK_TIMEOUT_MS.
677
+ */
678
+ async #uploadOwnedCredentialBlobs(
679
+ params: UploadCredentialBlobsParams & { credentialIds: [string] },
680
+ ): Promise<void> {
681
+ try {
682
+ await this.blobGateway.uploadCredentialBlobs(params);
683
+ } catch (error) {
684
+ if (!(error instanceof BlobGatewayUploadOutcomeUnknownError)) throw error;
685
+
686
+ const created = await this.getCredentialById(params.credentialIds[0]).catch(() => undefined);
687
+ if (!created?.content_uri) throw error;
688
+
689
+ const controller = new AbortController();
690
+ const timer = setTimeout(() => controller.abort(), READ_BACK_TIMEOUT_MS);
691
+ const stored = await this.blobGateway
692
+ .fetchBlob({
693
+ credentialId: created.id,
694
+ contentUri: created.content_uri,
695
+ expectedSize: created.content_size,
696
+ signal: controller.signal,
697
+ })
698
+ .catch(() => undefined)
699
+ .finally(() => clearTimeout(timer));
700
+ const uploaded = params.original ?? params.copy;
701
+ if (!stored || !bytesEqual(stored, uploaded)) throw error;
702
+ }
703
+ }
704
+
651
705
  async removeCredential(id: string): Promise<{ id: string }> {
652
706
  const credential = await this.getCredentialById(id);
653
707
  invariant(credential, `"idOSCredential" with id ${id} not found`);
654
708
 
655
709
  const contentUri = credential.content_uri ?? null;
656
- 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
+ }
657
713
 
658
714
  await removeCredential(this.kwilClient, { id });
659
715
 
@@ -743,7 +799,10 @@ export class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSig
743
799
  async getGrantsCount(): Promise<number> {
744
800
  return getAccessGrantsGrantedCount(this.kwilClient, {
745
801
  user_id: null,
746
- }).then((res) => res.count);
802
+ }).then((res) => {
803
+ if (!res) throw new Error("get_access_grants_granted_count returned no rows");
804
+ return res.count;
805
+ });
747
806
  }
748
807
 
749
808
  async getCredentialShared(id: string): Promise<idOSCredential | undefined> {
@@ -999,16 +1058,21 @@ export class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSig
999
1058
  // User issues the shared copy: sign content_uri with an ephemeral user-side key.
1000
1059
  // Copy issuer_auth_public_key need not match the original credential's issuer.
1001
1060
  const copyId = crypto.randomUUID();
1002
- const ukycContentUri = contentUriForWallet(this.walletType, this.kwilSigner, copyId);
1003
- requireAccessTokenForUkycContent(ukycContentUri, this.blobGateway.hasAccessToken);
1004
- const copyReference = ukycContentUri
1005
- ? { uri: ukycContentUri, size: content.byteLength }
1006
- : await createBlobContentReference(content);
1007
- const signedReference = buildEphemeralSignedCredentialContentReference("", copyReference.uri);
1061
+ const copyReference = await createBlobContentReference(content);
1062
+ const signedReference = await buildEphemeralSignedCredentialContentReference(
1063
+ "",
1064
+ copyReference.uri,
1065
+ (publicNotesSignature, contentUri) =>
1066
+ credentialBroaderMessage(this.kwilClient, {
1067
+ public_notes_signature: publicNotesSignature,
1068
+ content_uri: contentUri,
1069
+ recipient_wallet: credentialRecipientWallet(this),
1070
+ }).then((row) => row.message),
1071
+ );
1008
1072
 
1009
1073
  // Integrator-supplied. ed25519 @caller is lowercase hex; after exact grantee
1010
1074
  // matching, uppercase hex would store a grant the consumer cannot read. Other
1011
- // identifier encodings (NEAR, XRPL, Stellar, MM) are case-sensitive, so leave them.
1075
+ // identifier encodings (NEAR, XRPL, Stellar) are case-sensitive, so leave them.
1012
1076
  const granteeWalletIdentifier = /^[0-9a-fA-F]{64}$/.test(consumerAuthPublicKey)
1013
1077
  ? consumerAuthPublicKey.toLowerCase()
1014
1078
  : consumerAuthPublicKey;
@@ -1027,8 +1091,9 @@ export class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSig
1027
1091
  };
1028
1092
 
1029
1093
  await this.shareCredential(preliminaryCredential);
1030
- await this.blobGateway.uploadCredentialBlobs({
1094
+ await this.#uploadOwnedCredentialBlobs({
1031
1095
  requestId: preliminaryCredential.request_id,
1096
+ credentialIds: [copyId],
1032
1097
  copy: content,
1033
1098
  });
1034
1099