@notabene/javascript-sdk 2.9.0-next.1 → 2.9.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/notabene.cjs +1 -1
- package/dist/cjs/notabene.d.ts +16 -2
- package/dist/cjs/package.json +1 -1
- package/dist/esm/notabene.d.ts +16 -2
- package/dist/esm/notabene.js +117 -91
- package/dist/esm/package.json +1 -1
- package/dist/notabene.d.ts +16 -2
- package/dist/notabene.js +117 -91
- package/package.json +1 -1
- package/src/notabene.ts +5 -0
- package/src/utils/__tests__/connections.test.ts +24 -7
- package/src/utils/connections.ts +60 -2
- package/src/utils/encryption.ts +5 -3
package/dist/cjs/notabene.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var U=Object.defineProperty;var _=(t,e,n)=>e in t?U(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var a=(t,e,n)=>_(t,typeof e!="symbol"?e+"":e,n);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var f=(t=>(t.PRIVATE="WALLET",t.VASP="VASP",t))(f||{}),w=(t=>(t.NATURAL="natural",t.LEGAL="legal",t.SELF="self",t))(w||{}),g=(t=>(t.EMPTY="empty",t.VERIFY="verify",t.PENDING="pending",t.VERIFIED="verified",t.BANNED="banned",t))(g||{}),v=(t=>(t.ALLOWED="allowed",t.PENDING="pending",t))(v||{}),y=(t=>(t.ASSET="asset",t.DESTINATION="destination",t.COUNTERPARTY="counterparty",t.AGENT="agent",t))(y||{}),l=(t=>(t.COMPLETE="complete",t.RESIZE="resize",t.RESULT="result",t.READY="ready",t.INVALID="invalid",t.ERROR="error",t.CANCEL="cancel",t))(l||{}),A=(t=>(t.SERVICE_UNAVAILABLE="SERVICE_UNAVAILABLE",t.WALLET_CONNECTION_FAILED="WALLET_CONNECTION_FAILED",t.WALLET_NOT_SUPPORTED="WALLET_NOT_SUPPORTED",t.TOKEN_INVALID="TOKEN_INVALID",t))(A||{}),p=(t=>(t.UPDATE="update",t.REQUEST_RESPONSE="requestResponse",t))(p||{}),C=(t=>(t.PENDING="pending",t.FAILED="rejected",t.FLAGGED="flagged",t.VERIFIED="verified",t))(C||{}),b=(t=>(t.SelfDeclaration="self-declaration",t.SIWE="siwe",t.SIWX="siwx",t.EIP191="eip-191",t.EIP712="eip-712",t.EIP1271="eip-1271",t.BIP137="bip-137",t.BIP322="bip-322",t.BIP137_XPUB="xpub",t.TIP191="tip-191",t.ED25519="ed25519",t.XRP_ED25519="xrp-ed25519",t.XLM_ED25519="xlm-ed25519",t.CIP8="cip-8",t.MicroTransfer="microtransfer",t.Screenshot="screenshot",t.Connect="connect",t))(b||{});class R{constructor(){a(this,"listeners",new Map);a(this,"port");this.handleMessage=this.handleMessage.bind(this)}setPort(e){this.port=e,this.port.onmessage=this.handleMessage,this.port.start()}on(e,n){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(n),()=>this.off(e,n)}off(e,n){const r=this.listeners.get(e);r&&(r.delete(n),r.size===0&&this.listeners.delete(e))}handleMessage(e){const n=e.data;if(typeof n=="object"&&n!==null&&"type"in n){const r=n.type,s=this.listeners.get(r);s&&s.forEach(o=>o(n))}}send(e){this.port&&this.port.postMessage(e)}}class I{constructor(e,n,r){a(this,"_url");a(this,"_value");a(this,"_options");a(this,"_errors",[]);a(this,"iframe");a(this,"eventManager");a(this,"modal");this._url=e,this._value=n,this._options=r,this.eventManager=new R,this.on(l.INVALID,s=>{s.type===l.INVALID&&(this._errors=s.errors,this._value=s.value)}),this.on(l.RESIZE,s=>{s.type===l.RESIZE&&this.iframe&&(this.iframe.style.height=`${s.height}px`)})}get url(){return this._url}get value(){return this._value}get options(){return this._options}get errors(){return this._errors}open(){document.location.href=this.url}mount(e){const n=document.querySelector(e);if(!n)throw new Error(`parentID ${e} not found`);this.embed(n)}embed(e,n=!1){var r,s;this.removeEmbed(),this.iframe=document.createElement("iframe"),this.iframe.src=this.url+(n?"":"&embedded=true"),this.iframe.allow="web-share; clipboard-write; hid; bluetooth;",this.iframe.style.width="100%",this.iframe.style.height="0px",this.iframe.style.border="none",this.iframe.style.overflow="hidden",this.iframe.scrolling="no",e.appendChild(this.iframe),window.addEventListener("message",o=>{var i,c;o.source===((i=this.iframe)==null?void 0:i.contentWindow)&&((c=this.eventManager)==null||c.setPort(o.ports[0]))}),(s=(r=this.iframe)==null?void 0:r.contentWindow)==null||s.focus()}removeEmbed(){this.iframe&&this.iframe.remove()}send(e){this.eventManager.send(e)}on(e,n){return this.eventManager.on(e,n)}off(e,n){this.eventManager.off(e,n)}update(e,n){this._value=e,n&&(this._options=n),this.send({type:p.UPDATE,value:e,options:this._options})}completion(){return new Promise((e,n)=>{let r,s,o;function i(){r&&r(),s&&s(),o&&o()}r=this.on(l.COMPLETE,c=>{e(c.response),i()}),s=this.on(l.CANCEL,()=>{n(new Error("User cancelled")),i()}),o=this.on("error",c=>{n(new Error(c.message)),i()})})}async openModal(){this.modal&&this.closeModal(),this.modal=document.createElement("dialog"),this.modal.style.border="none",this.modal.style.backgroundColor="white",this.modal.style.maxWidth="100vw",this.modal.style.maxHeight="100vh",this.modal.style.width="600px",this.modal.style.height="600px",document.body.appendChild(this.modal),this.embed(this.modal,!0);const e=this.on(l.CANCEL,()=>{this.closeModal()}),n=this.on(l.COMPLETE,()=>{this.closeModal()});return this.modal.showModal(),this.modal.addEventListener("click",()=>{this.closeModal()}),this.completion().finally(()=>{e(),n()})}closeModal(){var e;this.modal&&((e=this.modal)==null||e.close(),this.modal.remove(),this.modal=void 0)}async popup(){const e=window.open(this.url,"_blank","popup=true,width=600,height=600");window.addEventListener("message",s=>{var o;s.source===e&&(console.log("received message from popup",s.data),(o=this.eventManager)==null||o.setPort(s.ports[0]))});const n=this.on(l.CANCEL,()=>{e==null||e.close()}),r=this.on(l.COMPLETE,()=>{e==null||e.close()});return this.completion().finally(()=>{n(),r()})}}function x(t){return Object.entries(t).map(([e,n])=>{if(n==null)return;const r=encodeURIComponent(e),s=encodeURIComponent(typeof n=="object"?JSON.stringify(n):String(n));return`${r}=${s}`}).filter(e=>e!==void 0).join("&")}function S(t){const e=t.slice(1);return e?e.split("&").filter(Boolean).reduce((r,s)=>{const[o,i]=s.split("=");return o&&(r[decodeURIComponent(o)]=i?decodeURIComponent(i):""),r},{}):{}}async function E(t,e){const n=JSON.stringify(t),r=new TextEncoder,s=e?m(e):crypto.getRandomValues(new Uint8Array(32)),o=await crypto.subtle.importKey("raw",s,{name:"AES-GCM"},!1,["encrypt"]),i=crypto.getRandomValues(new Uint8Array(12)),c=await crypto.subtle.encrypt({name:"AES-GCM",iv:i},o,r.encode(n));return{ciphertext:`${u(i)}-${u(c)}`,key:u(s)}}async function L({ciphertext:t,key:e}){const[n,r]=t.split("-"),s=new Uint8Array(atob(e).split("").map(N=>N.charCodeAt(0))),o=m(n),i=m(r),c=await crypto.subtle.importKey("raw",s,{name:"AES-GCM"},!1,["decrypt"]),d=new TextDecoder,h=await crypto.subtle.decrypt({name:"AES-GCM",iv:new Uint8Array(o)},c,i);return JSON.parse(d.decode(h))}function u(t){const e=new Uint8Array(t);let n="";for(let r=0;r<e.length;r++)n+=String.fromCharCode(e[r]);return btoa(n)}function m(t){const e=atob(t),n=new Uint8Array(e.length);for(let r=0;r<e.length;r++)n[r]=e.charCodeAt(r);return n}async function M(t){const e=await fetch(t.url,{method:"GET"});if(!e.ok)throw new Error(`Failed to get connection: ${await e.text()}`);const n=await e.json();if(!n.sealed)throw new Error("No data found");const r=n.sealed[n.sealed.length-1],s=await L({ciphertext:r,key:t.key});return{id:n.id,metadata:n.metadata,status:n.status,tx:s.tx,result:s.result}}class O{constructor(e){a(this,"endpoint");this.endpoint=e}async create(e,n){const r=await E(e),s={metadata:n,sealed:r.ciphertext},o=await fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw new Error(`Failed to create connection: ${await o.text()}`);const i=await o.json();return{id:i.id,version:i.version,status:i.status,metadata:n,data:e,key:r.key}}async update(e,n,r,s,o){const i=await E(n,o),c={sealed:i.ciphertext,version:r,status:s},d=await fetch(`${this.endpoint}/${e}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(c)});if(!d.ok)throw new Error(`Failed to update connection: ${await d.text()}`);const h=await d.json();return{id:h.id,metadata:h.metadata,version:h.version,status:h.status,data:n,key:i.key}}async get(e,n){const r=await fetch(`${this.endpoint}/${e}`,{method:"GET"});if(!r.ok)throw new Error(`Failed to get connection: ${await r.text()}`);const s=await r.json(),o=s.sealed[s.sealed.length-1],i=await L({ciphertext:o,key:n});return{id:s.id,status:s.status,version:s.version,metadata:s.metadata,data:i,key:n}}async close(e){const n=await fetch(`${this.endpoint}/${e}`,{method:"DELETE"});if(!n.ok)throw new Error(`Failed to close connection: ${await n.text()}`)}}class D{constructor(e){a(this,"nodeUrl");a(this,"authToken");a(this,"uxUrl");a(this,"theme");a(this,"locale");this.uxUrl=e.uxUrl||"https://connect.notabene.id",this.nodeUrl=e.nodeUrl,this.authToken=e.authToken,this.theme=e.theme,this.locale=e.locale}componentUrl(e,n,r,s){const o=new URL(this.uxUrl);o.pathname=e;const i=x({authToken:this.authToken,value:n,configuration:r});return o.hash=i,this.nodeUrl&&o.searchParams.set("nodeUrl",this.nodeUrl),this.theme&&o.searchParams.set("theme",JSON.stringify(this.theme)),this.locale&&o.searchParams.set("locale",this.locale),s&&(s.callback&&o.searchParams.set("callback_url",s.callback),s.redirectUri&&o.searchParams.set("redirect_uri",s.redirectUri)),o.toString()}createComponent(e,n,r,s){return new I(this.componentUrl(e,n,r,s),n,r)}createWithdrawalAssist(e,n,r){return this.createComponent("withdrawal-assist",e,n,r)}createConnectWallet(e,n,r){return this.createComponent("connect",e,n,r)}createDepositRequest(e,n,r){return this.createComponent("deposit-request",e,n,r)}createDepositAssist(e,n,r){return this.createComponent("deposit-assist",e,n,r)}}exports.AgentType=f;exports.CMType=l;exports.ConnectionManager=O;exports.EmbeddedComponent=I;exports.ErrorIdentifierCode=A;exports.HMType=p;exports.PersonType=w;exports.ProofStatus=C;exports.ProofTypes=b;exports.Status=g;exports.VASPSearchControl=v;exports.ValidationSections=y;exports.decodeFragmentToObject=S;exports.default=D;exports.getRefreshResult=M;
|
package/dist/cjs/notabene.d.ts
CHANGED
|
@@ -294,6 +294,7 @@ export declare interface ConnectionData<T extends ComponentRequest> {
|
|
|
294
294
|
tx: T;
|
|
295
295
|
authToken?: string;
|
|
296
296
|
txOptions?: TransactionOptions;
|
|
297
|
+
result?: TransactionResponse<T>;
|
|
297
298
|
}
|
|
298
299
|
|
|
299
300
|
/**
|
|
@@ -316,7 +317,7 @@ export declare class ConnectionManager {
|
|
|
316
317
|
* @param version Current version number
|
|
317
318
|
* @returns Promise resolving to updated connection details including new encryption key
|
|
318
319
|
*/
|
|
319
|
-
update<T extends ComponentRequest>(id: UUID, data: ConnectionData<T>, version: number): Promise<ConnectionResponse<T>>;
|
|
320
|
+
update<T extends ComponentRequest>(id: UUID, data: ConnectionData<T>, version: number, status: ConnectionStatus, key: string): Promise<ConnectionResponse<T>>;
|
|
320
321
|
/**
|
|
321
322
|
* Retrieves and decrypts connection data
|
|
322
323
|
* @param id Connection ID
|
|
@@ -354,11 +355,22 @@ export declare interface ConnectionRequest extends ComponentRequest {
|
|
|
354
355
|
export declare interface ConnectionResponse<T extends ComponentRequest> {
|
|
355
356
|
id: UUID;
|
|
356
357
|
version: number;
|
|
358
|
+
status: ConnectionStatus;
|
|
357
359
|
metadata: ConnectionMetadata;
|
|
358
360
|
data: ConnectionData<T>;
|
|
359
361
|
key: string;
|
|
360
362
|
}
|
|
361
363
|
|
|
364
|
+
export declare interface ConnectionResult<T extends ComponentRequest> {
|
|
365
|
+
id: UUID;
|
|
366
|
+
metadata: ConnectionMetadata;
|
|
367
|
+
status: ConnectionStatus;
|
|
368
|
+
tx: T;
|
|
369
|
+
result?: TransactionResponse<T>;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export declare type ConnectionStatus = 'active' | 'completed' | 'closed';
|
|
373
|
+
|
|
362
374
|
/**
|
|
363
375
|
* The counterparty of a transaction.
|
|
364
376
|
* @public
|
|
@@ -642,6 +654,8 @@ export declare type FieldTypes = {
|
|
|
642
654
|
legalPerson?: LegalPersonFields;
|
|
643
655
|
};
|
|
644
656
|
|
|
657
|
+
export declare function getRefreshResult<T extends ComponentRequest>(refreshSource: RefreshSource): Promise<ConnectionResult<T>>;
|
|
658
|
+
|
|
645
659
|
/**
|
|
646
660
|
* Host Message Type enum representing different message types that can be sent
|
|
647
661
|
* from the host application.
|
|
@@ -1352,7 +1366,7 @@ declare interface Refreshable {
|
|
|
1352
1366
|
refreshSource?: RefreshSource;
|
|
1353
1367
|
}
|
|
1354
1368
|
|
|
1355
|
-
declare interface RefreshSource {
|
|
1369
|
+
export declare interface RefreshSource {
|
|
1356
1370
|
url: URI;
|
|
1357
1371
|
key: string;
|
|
1358
1372
|
}
|
package/dist/cjs/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"author": "Notabene <developers@notabene.id>",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"packageManager": "yarn@4.5.1",
|
|
13
|
-
"version": "2.9.0-next.
|
|
13
|
+
"version": "2.9.0-next.2",
|
|
14
14
|
"source": "src/notabene.ts",
|
|
15
15
|
"main": "dist/cjs/notabene.cjs",
|
|
16
16
|
"module": "dist/esm/notabene.js",
|
package/dist/esm/notabene.d.ts
CHANGED
|
@@ -294,6 +294,7 @@ export declare interface ConnectionData<T extends ComponentRequest> {
|
|
|
294
294
|
tx: T;
|
|
295
295
|
authToken?: string;
|
|
296
296
|
txOptions?: TransactionOptions;
|
|
297
|
+
result?: TransactionResponse<T>;
|
|
297
298
|
}
|
|
298
299
|
|
|
299
300
|
/**
|
|
@@ -316,7 +317,7 @@ export declare class ConnectionManager {
|
|
|
316
317
|
* @param version Current version number
|
|
317
318
|
* @returns Promise resolving to updated connection details including new encryption key
|
|
318
319
|
*/
|
|
319
|
-
update<T extends ComponentRequest>(id: UUID, data: ConnectionData<T>, version: number): Promise<ConnectionResponse<T>>;
|
|
320
|
+
update<T extends ComponentRequest>(id: UUID, data: ConnectionData<T>, version: number, status: ConnectionStatus, key: string): Promise<ConnectionResponse<T>>;
|
|
320
321
|
/**
|
|
321
322
|
* Retrieves and decrypts connection data
|
|
322
323
|
* @param id Connection ID
|
|
@@ -354,11 +355,22 @@ export declare interface ConnectionRequest extends ComponentRequest {
|
|
|
354
355
|
export declare interface ConnectionResponse<T extends ComponentRequest> {
|
|
355
356
|
id: UUID;
|
|
356
357
|
version: number;
|
|
358
|
+
status: ConnectionStatus;
|
|
357
359
|
metadata: ConnectionMetadata;
|
|
358
360
|
data: ConnectionData<T>;
|
|
359
361
|
key: string;
|
|
360
362
|
}
|
|
361
363
|
|
|
364
|
+
export declare interface ConnectionResult<T extends ComponentRequest> {
|
|
365
|
+
id: UUID;
|
|
366
|
+
metadata: ConnectionMetadata;
|
|
367
|
+
status: ConnectionStatus;
|
|
368
|
+
tx: T;
|
|
369
|
+
result?: TransactionResponse<T>;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export declare type ConnectionStatus = 'active' | 'completed' | 'closed';
|
|
373
|
+
|
|
362
374
|
/**
|
|
363
375
|
* The counterparty of a transaction.
|
|
364
376
|
* @public
|
|
@@ -642,6 +654,8 @@ export declare type FieldTypes = {
|
|
|
642
654
|
legalPerson?: LegalPersonFields;
|
|
643
655
|
};
|
|
644
656
|
|
|
657
|
+
export declare function getRefreshResult<T extends ComponentRequest>(refreshSource: RefreshSource): Promise<ConnectionResult<T>>;
|
|
658
|
+
|
|
645
659
|
/**
|
|
646
660
|
* Host Message Type enum representing different message types that can be sent
|
|
647
661
|
* from the host application.
|
|
@@ -1352,7 +1366,7 @@ declare interface Refreshable {
|
|
|
1352
1366
|
refreshSource?: RefreshSource;
|
|
1353
1367
|
}
|
|
1354
1368
|
|
|
1355
|
-
declare interface RefreshSource {
|
|
1369
|
+
export declare interface RefreshSource {
|
|
1356
1370
|
url: URI;
|
|
1357
1371
|
key: string;
|
|
1358
1372
|
}
|
package/dist/esm/notabene.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var a = (t, e, n) =>
|
|
4
|
-
var A = /* @__PURE__ */ ((t) => (t.PRIVATE = "WALLET", t.VASP = "VASP", t))(A || {}),
|
|
5
|
-
class
|
|
1
|
+
var v = Object.defineProperty;
|
|
2
|
+
var g = (t, e, n) => e in t ? v(t, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : t[e] = n;
|
|
3
|
+
var a = (t, e, n) => g(t, typeof e != "symbol" ? e + "" : e, n);
|
|
4
|
+
var A = /* @__PURE__ */ ((t) => (t.PRIVATE = "WALLET", t.VASP = "VASP", t))(A || {}), y = /* @__PURE__ */ ((t) => (t.NATURAL = "natural", t.LEGAL = "legal", t.SELF = "self", t))(y || {}), I = /* @__PURE__ */ ((t) => (t.EMPTY = "empty", t.VERIFY = "verify", t.PENDING = "pending", t.VERIFIED = "verified", t.BANNED = "banned", t))(I || {}), L = /* @__PURE__ */ ((t) => (t.ALLOWED = "allowed", t.PENDING = "pending", t))(L || {}), C = /* @__PURE__ */ ((t) => (t.ASSET = "asset", t.DESTINATION = "destination", t.COUNTERPARTY = "counterparty", t.AGENT = "agent", t))(C || {}), l = /* @__PURE__ */ ((t) => (t.COMPLETE = "complete", t.RESIZE = "resize", t.RESULT = "result", t.READY = "ready", t.INVALID = "invalid", t.ERROR = "error", t.CANCEL = "cancel", t))(l || {}), N = /* @__PURE__ */ ((t) => (t.SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE", t.WALLET_CONNECTION_FAILED = "WALLET_CONNECTION_FAILED", t.WALLET_NOT_SUPPORTED = "WALLET_NOT_SUPPORTED", t.TOKEN_INVALID = "TOKEN_INVALID", t))(N || {}), E = /* @__PURE__ */ ((t) => (t.UPDATE = "update", t.REQUEST_RESPONSE = "requestResponse", t))(E || {}), b = /* @__PURE__ */ ((t) => (t.PENDING = "pending", t.FAILED = "rejected", t.FLAGGED = "flagged", t.VERIFIED = "verified", t))(b || {}), U = /* @__PURE__ */ ((t) => (t.SelfDeclaration = "self-declaration", t.SIWE = "siwe", t.SIWX = "siwx", t.EIP191 = "eip-191", t.EIP712 = "eip-712", t.EIP1271 = "eip-1271", t.BIP137 = "bip-137", t.BIP322 = "bip-322", t.BIP137_XPUB = "xpub", t.TIP191 = "tip-191", t.ED25519 = "ed25519", t.XRP_ED25519 = "xrp-ed25519", t.XLM_ED25519 = "xlm-ed25519", t.CIP8 = "cip-8", t.MicroTransfer = "microtransfer", t.Screenshot = "screenshot", t.Connect = "connect", t))(U || {});
|
|
5
|
+
class _ {
|
|
6
6
|
constructor() {
|
|
7
7
|
a(this, "listeners", /* @__PURE__ */ new Map());
|
|
8
8
|
a(this, "port");
|
|
@@ -56,8 +56,8 @@ class U {
|
|
|
56
56
|
handleMessage(e) {
|
|
57
57
|
const n = e.data;
|
|
58
58
|
if (typeof n == "object" && n !== null && "type" in n) {
|
|
59
|
-
const r = n.type,
|
|
60
|
-
|
|
59
|
+
const r = n.type, s = this.listeners.get(r);
|
|
60
|
+
s && s.forEach((i) => i(n));
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
@@ -68,7 +68,7 @@ class U {
|
|
|
68
68
|
this.port && this.port.postMessage(e);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
class
|
|
71
|
+
class x {
|
|
72
72
|
/**
|
|
73
73
|
* Creates an instance of EmbeddedComponent.
|
|
74
74
|
* @param url - The URL of the embedded component
|
|
@@ -82,10 +82,10 @@ class _ {
|
|
|
82
82
|
a(this, "iframe");
|
|
83
83
|
a(this, "eventManager");
|
|
84
84
|
a(this, "modal");
|
|
85
|
-
this._url = e, this._value = n, this._options = r, this.eventManager = new
|
|
86
|
-
|
|
87
|
-
}), this.on(l.RESIZE, (
|
|
88
|
-
|
|
85
|
+
this._url = e, this._value = n, this._options = r, this.eventManager = new _(), this.on(l.INVALID, (s) => {
|
|
86
|
+
s.type === l.INVALID && (this._errors = s.errors, this._value = s.value);
|
|
87
|
+
}), this.on(l.RESIZE, (s) => {
|
|
88
|
+
s.type === l.RESIZE && this.iframe && (this.iframe.style.height = `${s.height}px`);
|
|
89
89
|
});
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
@@ -129,11 +129,11 @@ class _ {
|
|
|
129
129
|
* @param parent - The parent element to embed the component into
|
|
130
130
|
*/
|
|
131
131
|
embed(e, n = !1) {
|
|
132
|
-
var r,
|
|
133
|
-
this.removeEmbed(), this.iframe = document.createElement("iframe"), this.iframe.src = this.url + (n ? "" : "&embedded=true"), this.iframe.allow = "web-share; clipboard-write; hid; bluetooth;", this.iframe.style.width = "100%", this.iframe.style.height = "0px", this.iframe.style.border = "none", this.iframe.style.overflow = "hidden", this.iframe.scrolling = "no", e.appendChild(this.iframe), window.addEventListener("message", (
|
|
132
|
+
var r, s;
|
|
133
|
+
this.removeEmbed(), this.iframe = document.createElement("iframe"), this.iframe.src = this.url + (n ? "" : "&embedded=true"), this.iframe.allow = "web-share; clipboard-write; hid; bluetooth;", this.iframe.style.width = "100%", this.iframe.style.height = "0px", this.iframe.style.border = "none", this.iframe.style.overflow = "hidden", this.iframe.scrolling = "no", e.appendChild(this.iframe), window.addEventListener("message", (i) => {
|
|
134
134
|
var o, c;
|
|
135
|
-
|
|
136
|
-
}), (
|
|
135
|
+
i.source === ((o = this.iframe) == null ? void 0 : o.contentWindow) && ((c = this.eventManager) == null || c.setPort(i.ports[0]));
|
|
136
|
+
}), (s = (r = this.iframe) == null ? void 0 : r.contentWindow) == null || s.focus();
|
|
137
137
|
}
|
|
138
138
|
removeEmbed() {
|
|
139
139
|
this.iframe && this.iframe.remove();
|
|
@@ -166,7 +166,7 @@ class _ {
|
|
|
166
166
|
* @param value - The new transaction value
|
|
167
167
|
*/
|
|
168
168
|
update(e, n) {
|
|
169
|
-
this._value = e, n && (this._options = n), this.send({ type:
|
|
169
|
+
this._value = e, n && (this._options = n), this.send({ type: E.UPDATE, value: e, options: this._options });
|
|
170
170
|
}
|
|
171
171
|
/**
|
|
172
172
|
* Waits for the component to complete and returns the transaction response
|
|
@@ -174,15 +174,15 @@ class _ {
|
|
|
174
174
|
*/
|
|
175
175
|
completion() {
|
|
176
176
|
return new Promise((e, n) => {
|
|
177
|
-
let r,
|
|
177
|
+
let r, s, i;
|
|
178
178
|
function o() {
|
|
179
|
-
r && r(),
|
|
179
|
+
r && r(), s && s(), i && i();
|
|
180
180
|
}
|
|
181
181
|
r = this.on(l.COMPLETE, (c) => {
|
|
182
182
|
e(c.response), o();
|
|
183
|
-
}),
|
|
183
|
+
}), s = this.on(l.CANCEL, () => {
|
|
184
184
|
n(new Error("User cancelled")), o();
|
|
185
|
-
}),
|
|
185
|
+
}), i = this.on("error", (c) => {
|
|
186
186
|
n(new Error(c.message)), o();
|
|
187
187
|
});
|
|
188
188
|
});
|
|
@@ -223,9 +223,9 @@ class _ {
|
|
|
223
223
|
"_blank",
|
|
224
224
|
"popup=true,width=600,height=600"
|
|
225
225
|
);
|
|
226
|
-
window.addEventListener("message", (
|
|
227
|
-
var
|
|
228
|
-
|
|
226
|
+
window.addEventListener("message", (s) => {
|
|
227
|
+
var i;
|
|
228
|
+
s.source === e && (console.log("received message from popup", s.data), (i = this.eventManager) == null || i.setPort(s.ports[0]));
|
|
229
229
|
});
|
|
230
230
|
const n = this.on(l.CANCEL, () => {
|
|
231
231
|
e == null || e.close();
|
|
@@ -237,60 +237,60 @@ class _ {
|
|
|
237
237
|
});
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
|
-
function
|
|
240
|
+
function R(t) {
|
|
241
241
|
return Object.entries(t).map(([e, n]) => {
|
|
242
242
|
if (n == null) return;
|
|
243
|
-
const r = encodeURIComponent(e),
|
|
243
|
+
const r = encodeURIComponent(e), s = encodeURIComponent(
|
|
244
244
|
typeof n == "object" ? JSON.stringify(n) : String(n)
|
|
245
245
|
// Use String() to handle all primitive types
|
|
246
246
|
);
|
|
247
|
-
return `${r}=${
|
|
247
|
+
return `${r}=${s}`;
|
|
248
248
|
}).filter((e) => e !== void 0).join("&");
|
|
249
249
|
}
|
|
250
250
|
function O(t) {
|
|
251
251
|
const e = t.slice(1);
|
|
252
252
|
return e ? e.split("&").filter(Boolean).reduce(
|
|
253
|
-
(r,
|
|
254
|
-
const [
|
|
255
|
-
return
|
|
253
|
+
(r, s) => {
|
|
254
|
+
const [i, o] = s.split("=");
|
|
255
|
+
return i && (r[decodeURIComponent(i)] = o ? decodeURIComponent(o) : ""), r;
|
|
256
256
|
},
|
|
257
257
|
{}
|
|
258
258
|
) : {};
|
|
259
259
|
}
|
|
260
|
-
async function
|
|
261
|
-
const
|
|
260
|
+
async function p(t, e) {
|
|
261
|
+
const n = JSON.stringify(t), r = new TextEncoder(), s = e ? m(e) : crypto.getRandomValues(new Uint8Array(32)), i = await crypto.subtle.importKey(
|
|
262
262
|
"raw",
|
|
263
|
-
|
|
263
|
+
s,
|
|
264
264
|
{ name: "AES-GCM" },
|
|
265
265
|
!1,
|
|
266
266
|
["encrypt"]
|
|
267
|
-
),
|
|
268
|
-
{ name: "AES-GCM", iv:
|
|
267
|
+
), o = crypto.getRandomValues(new Uint8Array(12)), c = await crypto.subtle.encrypt(
|
|
268
|
+
{ name: "AES-GCM", iv: o },
|
|
269
269
|
i,
|
|
270
|
-
|
|
270
|
+
r.encode(n)
|
|
271
271
|
);
|
|
272
272
|
return {
|
|
273
|
-
ciphertext: `${
|
|
274
|
-
key:
|
|
273
|
+
ciphertext: `${u(o)}-${u(c)}`,
|
|
274
|
+
key: u(s)
|
|
275
275
|
};
|
|
276
276
|
}
|
|
277
|
-
async function
|
|
278
|
-
const [n, r] = t.split("-"),
|
|
279
|
-
atob(e).split("").map((
|
|
280
|
-
),
|
|
277
|
+
async function f({ ciphertext: t, key: e }) {
|
|
278
|
+
const [n, r] = t.split("-"), s = new Uint8Array(
|
|
279
|
+
atob(e).split("").map((w) => w.charCodeAt(0))
|
|
280
|
+
), i = m(n), o = m(r), c = await crypto.subtle.importKey(
|
|
281
281
|
"raw",
|
|
282
|
-
|
|
282
|
+
s,
|
|
283
283
|
{ name: "AES-GCM" },
|
|
284
284
|
!1,
|
|
285
285
|
["decrypt"]
|
|
286
|
-
),
|
|
287
|
-
{ name: "AES-GCM", iv: new Uint8Array(
|
|
286
|
+
), h = new TextDecoder(), d = await crypto.subtle.decrypt(
|
|
287
|
+
{ name: "AES-GCM", iv: new Uint8Array(i) },
|
|
288
288
|
c,
|
|
289
289
|
o
|
|
290
290
|
);
|
|
291
|
-
return JSON.parse(
|
|
291
|
+
return JSON.parse(h.decode(d));
|
|
292
292
|
}
|
|
293
|
-
function
|
|
293
|
+
function u(t) {
|
|
294
294
|
const e = new Uint8Array(t);
|
|
295
295
|
let n = "";
|
|
296
296
|
for (let r = 0; r < e.length; r++)
|
|
@@ -303,7 +303,28 @@ function m(t) {
|
|
|
303
303
|
n[r] = e.charCodeAt(r);
|
|
304
304
|
return n;
|
|
305
305
|
}
|
|
306
|
-
|
|
306
|
+
async function M(t) {
|
|
307
|
+
const e = await fetch(t.url, {
|
|
308
|
+
method: "GET"
|
|
309
|
+
});
|
|
310
|
+
if (!e.ok)
|
|
311
|
+
throw new Error(`Failed to get connection: ${await e.text()}`);
|
|
312
|
+
const n = await e.json();
|
|
313
|
+
if (!n.sealed)
|
|
314
|
+
throw new Error("No data found");
|
|
315
|
+
const r = n.sealed[n.sealed.length - 1], s = await f({
|
|
316
|
+
ciphertext: r,
|
|
317
|
+
key: t.key
|
|
318
|
+
});
|
|
319
|
+
return {
|
|
320
|
+
id: n.id,
|
|
321
|
+
metadata: n.metadata,
|
|
322
|
+
status: n.status,
|
|
323
|
+
tx: s.tx,
|
|
324
|
+
result: s.result
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
class S {
|
|
307
328
|
constructor(e) {
|
|
308
329
|
a(this, "endpoint");
|
|
309
330
|
this.endpoint = e;
|
|
@@ -315,22 +336,23 @@ class M {
|
|
|
315
336
|
* @returns Promise resolving to connection details including ID, version, and encryption key
|
|
316
337
|
*/
|
|
317
338
|
async create(e, n) {
|
|
318
|
-
const r = await
|
|
339
|
+
const r = await p(e), s = {
|
|
319
340
|
metadata: n,
|
|
320
341
|
sealed: r.ciphertext
|
|
321
|
-
},
|
|
342
|
+
}, i = await fetch(this.endpoint, {
|
|
322
343
|
method: "POST",
|
|
323
344
|
headers: {
|
|
324
345
|
"Content-Type": "application/json"
|
|
325
346
|
},
|
|
326
|
-
body: JSON.stringify(
|
|
347
|
+
body: JSON.stringify(s)
|
|
327
348
|
});
|
|
328
|
-
if (!
|
|
329
|
-
throw new Error(`Failed to create connection: ${await
|
|
330
|
-
const o = await
|
|
349
|
+
if (!i.ok)
|
|
350
|
+
throw new Error(`Failed to create connection: ${await i.text()}`);
|
|
351
|
+
const o = await i.json();
|
|
331
352
|
return {
|
|
332
353
|
id: o.id,
|
|
333
354
|
version: o.version,
|
|
355
|
+
status: o.status,
|
|
334
356
|
metadata: n,
|
|
335
357
|
data: e,
|
|
336
358
|
key: r.key
|
|
@@ -343,26 +365,28 @@ class M {
|
|
|
343
365
|
* @param version Current version number
|
|
344
366
|
* @returns Promise resolving to updated connection details including new encryption key
|
|
345
367
|
*/
|
|
346
|
-
async update(e, n, r) {
|
|
347
|
-
const
|
|
348
|
-
sealed:
|
|
349
|
-
version: r
|
|
350
|
-
|
|
368
|
+
async update(e, n, r, s, i) {
|
|
369
|
+
const o = await p(n, i), c = {
|
|
370
|
+
sealed: o.ciphertext,
|
|
371
|
+
version: r,
|
|
372
|
+
status: s
|
|
373
|
+
}, h = await fetch(`${this.endpoint}/${e}`, {
|
|
351
374
|
method: "PATCH",
|
|
352
375
|
headers: {
|
|
353
376
|
"Content-Type": "application/json"
|
|
354
377
|
},
|
|
355
|
-
body: JSON.stringify(
|
|
378
|
+
body: JSON.stringify(c)
|
|
356
379
|
});
|
|
357
|
-
if (!
|
|
358
|
-
throw new Error(`Failed to update connection: ${await
|
|
359
|
-
const
|
|
380
|
+
if (!h.ok)
|
|
381
|
+
throw new Error(`Failed to update connection: ${await h.text()}`);
|
|
382
|
+
const d = await h.json();
|
|
360
383
|
return {
|
|
361
|
-
id:
|
|
362
|
-
metadata:
|
|
363
|
-
version:
|
|
384
|
+
id: d.id,
|
|
385
|
+
metadata: d.metadata,
|
|
386
|
+
version: d.version,
|
|
387
|
+
status: d.status,
|
|
364
388
|
data: n,
|
|
365
|
-
key:
|
|
389
|
+
key: o.key
|
|
366
390
|
};
|
|
367
391
|
}
|
|
368
392
|
/**
|
|
@@ -377,14 +401,15 @@ class M {
|
|
|
377
401
|
});
|
|
378
402
|
if (!r.ok)
|
|
379
403
|
throw new Error(`Failed to get connection: ${await r.text()}`);
|
|
380
|
-
const
|
|
381
|
-
ciphertext:
|
|
404
|
+
const s = await r.json(), i = s.sealed[s.sealed.length - 1], o = await f({
|
|
405
|
+
ciphertext: i,
|
|
382
406
|
key: n
|
|
383
407
|
});
|
|
384
408
|
return {
|
|
385
|
-
id:
|
|
386
|
-
|
|
387
|
-
|
|
409
|
+
id: s.id,
|
|
410
|
+
status: s.status,
|
|
411
|
+
version: s.version,
|
|
412
|
+
metadata: s.metadata,
|
|
388
413
|
data: o,
|
|
389
414
|
key: n
|
|
390
415
|
};
|
|
@@ -401,7 +426,7 @@ class M {
|
|
|
401
426
|
throw new Error(`Failed to close connection: ${await n.text()}`);
|
|
402
427
|
}
|
|
403
428
|
}
|
|
404
|
-
class
|
|
429
|
+
class k {
|
|
405
430
|
/**
|
|
406
431
|
* Creates a new instance of the Notabene SDK
|
|
407
432
|
*
|
|
@@ -425,15 +450,15 @@ class S {
|
|
|
425
450
|
* @returns component URL
|
|
426
451
|
* @internal
|
|
427
452
|
*/
|
|
428
|
-
componentUrl(e, n, r,
|
|
429
|
-
const
|
|
430
|
-
|
|
431
|
-
const o =
|
|
453
|
+
componentUrl(e, n, r, s) {
|
|
454
|
+
const i = new URL(this.uxUrl);
|
|
455
|
+
i.pathname = e;
|
|
456
|
+
const o = R({
|
|
432
457
|
authToken: this.authToken,
|
|
433
458
|
value: n,
|
|
434
459
|
configuration: r
|
|
435
460
|
});
|
|
436
|
-
return
|
|
461
|
+
return i.hash = o, this.nodeUrl && i.searchParams.set("nodeUrl", this.nodeUrl), this.theme && i.searchParams.set("theme", JSON.stringify(this.theme)), this.locale && i.searchParams.set("locale", this.locale), s && (s.callback && i.searchParams.set("callback_url", s.callback), s.redirectUri && i.searchParams.set("redirect_uri", s.redirectUri)), i.toString();
|
|
437
462
|
}
|
|
438
463
|
/**
|
|
439
464
|
* Creates a new embedded component
|
|
@@ -445,9 +470,9 @@ class S {
|
|
|
445
470
|
* @returns A new EmbeddedComponent instance
|
|
446
471
|
* @internal
|
|
447
472
|
*/
|
|
448
|
-
createComponent(e, n, r,
|
|
449
|
-
return new
|
|
450
|
-
this.componentUrl(e, n, r,
|
|
473
|
+
createComponent(e, n, r, s) {
|
|
474
|
+
return new x(
|
|
475
|
+
this.componentUrl(e, n, r, s),
|
|
451
476
|
n,
|
|
452
477
|
r
|
|
453
478
|
);
|
|
@@ -523,16 +548,17 @@ class S {
|
|
|
523
548
|
export {
|
|
524
549
|
A as AgentType,
|
|
525
550
|
l as CMType,
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
551
|
+
S as ConnectionManager,
|
|
552
|
+
x as EmbeddedComponent,
|
|
553
|
+
N as ErrorIdentifierCode,
|
|
554
|
+
E as HMType,
|
|
555
|
+
y as PersonType,
|
|
531
556
|
b as ProofStatus,
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
557
|
+
U as ProofTypes,
|
|
558
|
+
I as Status,
|
|
559
|
+
L as VASPSearchControl,
|
|
560
|
+
C as ValidationSections,
|
|
536
561
|
O as decodeFragmentToObject,
|
|
537
|
-
|
|
562
|
+
k as default,
|
|
563
|
+
M as getRefreshResult
|
|
538
564
|
};
|
package/dist/esm/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"author": "Notabene <developers@notabene.id>",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"packageManager": "yarn@4.5.1",
|
|
13
|
-
"version": "2.9.0-next.
|
|
13
|
+
"version": "2.9.0-next.2",
|
|
14
14
|
"source": "src/notabene.ts",
|
|
15
15
|
"main": "dist/cjs/notabene.cjs",
|
|
16
16
|
"module": "dist/esm/notabene.js",
|
package/dist/notabene.d.ts
CHANGED
|
@@ -294,6 +294,7 @@ export declare interface ConnectionData<T extends ComponentRequest> {
|
|
|
294
294
|
tx: T;
|
|
295
295
|
authToken?: string;
|
|
296
296
|
txOptions?: TransactionOptions;
|
|
297
|
+
result?: TransactionResponse<T>;
|
|
297
298
|
}
|
|
298
299
|
|
|
299
300
|
/**
|
|
@@ -316,7 +317,7 @@ export declare class ConnectionManager {
|
|
|
316
317
|
* @param version Current version number
|
|
317
318
|
* @returns Promise resolving to updated connection details including new encryption key
|
|
318
319
|
*/
|
|
319
|
-
update<T extends ComponentRequest>(id: UUID, data: ConnectionData<T>, version: number): Promise<ConnectionResponse<T>>;
|
|
320
|
+
update<T extends ComponentRequest>(id: UUID, data: ConnectionData<T>, version: number, status: ConnectionStatus, key: string): Promise<ConnectionResponse<T>>;
|
|
320
321
|
/**
|
|
321
322
|
* Retrieves and decrypts connection data
|
|
322
323
|
* @param id Connection ID
|
|
@@ -354,11 +355,22 @@ export declare interface ConnectionRequest extends ComponentRequest {
|
|
|
354
355
|
export declare interface ConnectionResponse<T extends ComponentRequest> {
|
|
355
356
|
id: UUID;
|
|
356
357
|
version: number;
|
|
358
|
+
status: ConnectionStatus;
|
|
357
359
|
metadata: ConnectionMetadata;
|
|
358
360
|
data: ConnectionData<T>;
|
|
359
361
|
key: string;
|
|
360
362
|
}
|
|
361
363
|
|
|
364
|
+
export declare interface ConnectionResult<T extends ComponentRequest> {
|
|
365
|
+
id: UUID;
|
|
366
|
+
metadata: ConnectionMetadata;
|
|
367
|
+
status: ConnectionStatus;
|
|
368
|
+
tx: T;
|
|
369
|
+
result?: TransactionResponse<T>;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export declare type ConnectionStatus = 'active' | 'completed' | 'closed';
|
|
373
|
+
|
|
362
374
|
/**
|
|
363
375
|
* The counterparty of a transaction.
|
|
364
376
|
* @public
|
|
@@ -642,6 +654,8 @@ export declare type FieldTypes = {
|
|
|
642
654
|
legalPerson?: LegalPersonFields;
|
|
643
655
|
};
|
|
644
656
|
|
|
657
|
+
export declare function getRefreshResult<T extends ComponentRequest>(refreshSource: RefreshSource): Promise<ConnectionResult<T>>;
|
|
658
|
+
|
|
645
659
|
/**
|
|
646
660
|
* Host Message Type enum representing different message types that can be sent
|
|
647
661
|
* from the host application.
|
|
@@ -1352,7 +1366,7 @@ declare interface Refreshable {
|
|
|
1352
1366
|
refreshSource?: RefreshSource;
|
|
1353
1367
|
}
|
|
1354
1368
|
|
|
1355
|
-
declare interface RefreshSource {
|
|
1369
|
+
export declare interface RefreshSource {
|
|
1356
1370
|
url: URI;
|
|
1357
1371
|
key: string;
|
|
1358
1372
|
}
|
package/dist/notabene.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var a = (t, e, n) =>
|
|
4
|
-
var A = /* @__PURE__ */ ((t) => (t.PRIVATE = "WALLET", t.VASP = "VASP", t))(A || {}),
|
|
5
|
-
class
|
|
1
|
+
var v = Object.defineProperty;
|
|
2
|
+
var g = (t, e, n) => e in t ? v(t, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : t[e] = n;
|
|
3
|
+
var a = (t, e, n) => g(t, typeof e != "symbol" ? e + "" : e, n);
|
|
4
|
+
var A = /* @__PURE__ */ ((t) => (t.PRIVATE = "WALLET", t.VASP = "VASP", t))(A || {}), y = /* @__PURE__ */ ((t) => (t.NATURAL = "natural", t.LEGAL = "legal", t.SELF = "self", t))(y || {}), I = /* @__PURE__ */ ((t) => (t.EMPTY = "empty", t.VERIFY = "verify", t.PENDING = "pending", t.VERIFIED = "verified", t.BANNED = "banned", t))(I || {}), L = /* @__PURE__ */ ((t) => (t.ALLOWED = "allowed", t.PENDING = "pending", t))(L || {}), C = /* @__PURE__ */ ((t) => (t.ASSET = "asset", t.DESTINATION = "destination", t.COUNTERPARTY = "counterparty", t.AGENT = "agent", t))(C || {}), l = /* @__PURE__ */ ((t) => (t.COMPLETE = "complete", t.RESIZE = "resize", t.RESULT = "result", t.READY = "ready", t.INVALID = "invalid", t.ERROR = "error", t.CANCEL = "cancel", t))(l || {}), N = /* @__PURE__ */ ((t) => (t.SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE", t.WALLET_CONNECTION_FAILED = "WALLET_CONNECTION_FAILED", t.WALLET_NOT_SUPPORTED = "WALLET_NOT_SUPPORTED", t.TOKEN_INVALID = "TOKEN_INVALID", t))(N || {}), E = /* @__PURE__ */ ((t) => (t.UPDATE = "update", t.REQUEST_RESPONSE = "requestResponse", t))(E || {}), b = /* @__PURE__ */ ((t) => (t.PENDING = "pending", t.FAILED = "rejected", t.FLAGGED = "flagged", t.VERIFIED = "verified", t))(b || {}), U = /* @__PURE__ */ ((t) => (t.SelfDeclaration = "self-declaration", t.SIWE = "siwe", t.SIWX = "siwx", t.EIP191 = "eip-191", t.EIP712 = "eip-712", t.EIP1271 = "eip-1271", t.BIP137 = "bip-137", t.BIP322 = "bip-322", t.BIP137_XPUB = "xpub", t.TIP191 = "tip-191", t.ED25519 = "ed25519", t.XRP_ED25519 = "xrp-ed25519", t.XLM_ED25519 = "xlm-ed25519", t.CIP8 = "cip-8", t.MicroTransfer = "microtransfer", t.Screenshot = "screenshot", t.Connect = "connect", t))(U || {});
|
|
5
|
+
class _ {
|
|
6
6
|
constructor() {
|
|
7
7
|
a(this, "listeners", /* @__PURE__ */ new Map());
|
|
8
8
|
a(this, "port");
|
|
@@ -56,8 +56,8 @@ class U {
|
|
|
56
56
|
handleMessage(e) {
|
|
57
57
|
const n = e.data;
|
|
58
58
|
if (typeof n == "object" && n !== null && "type" in n) {
|
|
59
|
-
const r = n.type,
|
|
60
|
-
|
|
59
|
+
const r = n.type, s = this.listeners.get(r);
|
|
60
|
+
s && s.forEach((i) => i(n));
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
@@ -68,7 +68,7 @@ class U {
|
|
|
68
68
|
this.port && this.port.postMessage(e);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
class
|
|
71
|
+
class x {
|
|
72
72
|
/**
|
|
73
73
|
* Creates an instance of EmbeddedComponent.
|
|
74
74
|
* @param url - The URL of the embedded component
|
|
@@ -82,10 +82,10 @@ class _ {
|
|
|
82
82
|
a(this, "iframe");
|
|
83
83
|
a(this, "eventManager");
|
|
84
84
|
a(this, "modal");
|
|
85
|
-
this._url = e, this._value = n, this._options = r, this.eventManager = new
|
|
86
|
-
|
|
87
|
-
}), this.on(l.RESIZE, (
|
|
88
|
-
|
|
85
|
+
this._url = e, this._value = n, this._options = r, this.eventManager = new _(), this.on(l.INVALID, (s) => {
|
|
86
|
+
s.type === l.INVALID && (this._errors = s.errors, this._value = s.value);
|
|
87
|
+
}), this.on(l.RESIZE, (s) => {
|
|
88
|
+
s.type === l.RESIZE && this.iframe && (this.iframe.style.height = `${s.height}px`);
|
|
89
89
|
});
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
@@ -129,11 +129,11 @@ class _ {
|
|
|
129
129
|
* @param parent - The parent element to embed the component into
|
|
130
130
|
*/
|
|
131
131
|
embed(e, n = !1) {
|
|
132
|
-
var r,
|
|
133
|
-
this.removeEmbed(), this.iframe = document.createElement("iframe"), this.iframe.src = this.url + (n ? "" : "&embedded=true"), this.iframe.allow = "web-share; clipboard-write; hid; bluetooth;", this.iframe.style.width = "100%", this.iframe.style.height = "0px", this.iframe.style.border = "none", this.iframe.style.overflow = "hidden", this.iframe.scrolling = "no", e.appendChild(this.iframe), window.addEventListener("message", (
|
|
132
|
+
var r, s;
|
|
133
|
+
this.removeEmbed(), this.iframe = document.createElement("iframe"), this.iframe.src = this.url + (n ? "" : "&embedded=true"), this.iframe.allow = "web-share; clipboard-write; hid; bluetooth;", this.iframe.style.width = "100%", this.iframe.style.height = "0px", this.iframe.style.border = "none", this.iframe.style.overflow = "hidden", this.iframe.scrolling = "no", e.appendChild(this.iframe), window.addEventListener("message", (i) => {
|
|
134
134
|
var o, c;
|
|
135
|
-
|
|
136
|
-
}), (
|
|
135
|
+
i.source === ((o = this.iframe) == null ? void 0 : o.contentWindow) && ((c = this.eventManager) == null || c.setPort(i.ports[0]));
|
|
136
|
+
}), (s = (r = this.iframe) == null ? void 0 : r.contentWindow) == null || s.focus();
|
|
137
137
|
}
|
|
138
138
|
removeEmbed() {
|
|
139
139
|
this.iframe && this.iframe.remove();
|
|
@@ -166,7 +166,7 @@ class _ {
|
|
|
166
166
|
* @param value - The new transaction value
|
|
167
167
|
*/
|
|
168
168
|
update(e, n) {
|
|
169
|
-
this._value = e, n && (this._options = n), this.send({ type:
|
|
169
|
+
this._value = e, n && (this._options = n), this.send({ type: E.UPDATE, value: e, options: this._options });
|
|
170
170
|
}
|
|
171
171
|
/**
|
|
172
172
|
* Waits for the component to complete and returns the transaction response
|
|
@@ -174,15 +174,15 @@ class _ {
|
|
|
174
174
|
*/
|
|
175
175
|
completion() {
|
|
176
176
|
return new Promise((e, n) => {
|
|
177
|
-
let r,
|
|
177
|
+
let r, s, i;
|
|
178
178
|
function o() {
|
|
179
|
-
r && r(),
|
|
179
|
+
r && r(), s && s(), i && i();
|
|
180
180
|
}
|
|
181
181
|
r = this.on(l.COMPLETE, (c) => {
|
|
182
182
|
e(c.response), o();
|
|
183
|
-
}),
|
|
183
|
+
}), s = this.on(l.CANCEL, () => {
|
|
184
184
|
n(new Error("User cancelled")), o();
|
|
185
|
-
}),
|
|
185
|
+
}), i = this.on("error", (c) => {
|
|
186
186
|
n(new Error(c.message)), o();
|
|
187
187
|
});
|
|
188
188
|
});
|
|
@@ -223,9 +223,9 @@ class _ {
|
|
|
223
223
|
"_blank",
|
|
224
224
|
"popup=true,width=600,height=600"
|
|
225
225
|
);
|
|
226
|
-
window.addEventListener("message", (
|
|
227
|
-
var
|
|
228
|
-
|
|
226
|
+
window.addEventListener("message", (s) => {
|
|
227
|
+
var i;
|
|
228
|
+
s.source === e && (console.log("received message from popup", s.data), (i = this.eventManager) == null || i.setPort(s.ports[0]));
|
|
229
229
|
});
|
|
230
230
|
const n = this.on(l.CANCEL, () => {
|
|
231
231
|
e == null || e.close();
|
|
@@ -237,60 +237,60 @@ class _ {
|
|
|
237
237
|
});
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
|
-
function
|
|
240
|
+
function R(t) {
|
|
241
241
|
return Object.entries(t).map(([e, n]) => {
|
|
242
242
|
if (n == null) return;
|
|
243
|
-
const r = encodeURIComponent(e),
|
|
243
|
+
const r = encodeURIComponent(e), s = encodeURIComponent(
|
|
244
244
|
typeof n == "object" ? JSON.stringify(n) : String(n)
|
|
245
245
|
// Use String() to handle all primitive types
|
|
246
246
|
);
|
|
247
|
-
return `${r}=${
|
|
247
|
+
return `${r}=${s}`;
|
|
248
248
|
}).filter((e) => e !== void 0).join("&");
|
|
249
249
|
}
|
|
250
250
|
function O(t) {
|
|
251
251
|
const e = t.slice(1);
|
|
252
252
|
return e ? e.split("&").filter(Boolean).reduce(
|
|
253
|
-
(r,
|
|
254
|
-
const [
|
|
255
|
-
return
|
|
253
|
+
(r, s) => {
|
|
254
|
+
const [i, o] = s.split("=");
|
|
255
|
+
return i && (r[decodeURIComponent(i)] = o ? decodeURIComponent(o) : ""), r;
|
|
256
256
|
},
|
|
257
257
|
{}
|
|
258
258
|
) : {};
|
|
259
259
|
}
|
|
260
|
-
async function
|
|
261
|
-
const
|
|
260
|
+
async function p(t, e) {
|
|
261
|
+
const n = JSON.stringify(t), r = new TextEncoder(), s = e ? m(e) : crypto.getRandomValues(new Uint8Array(32)), i = await crypto.subtle.importKey(
|
|
262
262
|
"raw",
|
|
263
|
-
|
|
263
|
+
s,
|
|
264
264
|
{ name: "AES-GCM" },
|
|
265
265
|
!1,
|
|
266
266
|
["encrypt"]
|
|
267
|
-
),
|
|
268
|
-
{ name: "AES-GCM", iv:
|
|
267
|
+
), o = crypto.getRandomValues(new Uint8Array(12)), c = await crypto.subtle.encrypt(
|
|
268
|
+
{ name: "AES-GCM", iv: o },
|
|
269
269
|
i,
|
|
270
|
-
|
|
270
|
+
r.encode(n)
|
|
271
271
|
);
|
|
272
272
|
return {
|
|
273
|
-
ciphertext: `${
|
|
274
|
-
key:
|
|
273
|
+
ciphertext: `${u(o)}-${u(c)}`,
|
|
274
|
+
key: u(s)
|
|
275
275
|
};
|
|
276
276
|
}
|
|
277
|
-
async function
|
|
278
|
-
const [n, r] = t.split("-"),
|
|
279
|
-
atob(e).split("").map((
|
|
280
|
-
),
|
|
277
|
+
async function f({ ciphertext: t, key: e }) {
|
|
278
|
+
const [n, r] = t.split("-"), s = new Uint8Array(
|
|
279
|
+
atob(e).split("").map((w) => w.charCodeAt(0))
|
|
280
|
+
), i = m(n), o = m(r), c = await crypto.subtle.importKey(
|
|
281
281
|
"raw",
|
|
282
|
-
|
|
282
|
+
s,
|
|
283
283
|
{ name: "AES-GCM" },
|
|
284
284
|
!1,
|
|
285
285
|
["decrypt"]
|
|
286
|
-
),
|
|
287
|
-
{ name: "AES-GCM", iv: new Uint8Array(
|
|
286
|
+
), h = new TextDecoder(), d = await crypto.subtle.decrypt(
|
|
287
|
+
{ name: "AES-GCM", iv: new Uint8Array(i) },
|
|
288
288
|
c,
|
|
289
289
|
o
|
|
290
290
|
);
|
|
291
|
-
return JSON.parse(
|
|
291
|
+
return JSON.parse(h.decode(d));
|
|
292
292
|
}
|
|
293
|
-
function
|
|
293
|
+
function u(t) {
|
|
294
294
|
const e = new Uint8Array(t);
|
|
295
295
|
let n = "";
|
|
296
296
|
for (let r = 0; r < e.length; r++)
|
|
@@ -303,7 +303,28 @@ function m(t) {
|
|
|
303
303
|
n[r] = e.charCodeAt(r);
|
|
304
304
|
return n;
|
|
305
305
|
}
|
|
306
|
-
|
|
306
|
+
async function M(t) {
|
|
307
|
+
const e = await fetch(t.url, {
|
|
308
|
+
method: "GET"
|
|
309
|
+
});
|
|
310
|
+
if (!e.ok)
|
|
311
|
+
throw new Error(`Failed to get connection: ${await e.text()}`);
|
|
312
|
+
const n = await e.json();
|
|
313
|
+
if (!n.sealed)
|
|
314
|
+
throw new Error("No data found");
|
|
315
|
+
const r = n.sealed[n.sealed.length - 1], s = await f({
|
|
316
|
+
ciphertext: r,
|
|
317
|
+
key: t.key
|
|
318
|
+
});
|
|
319
|
+
return {
|
|
320
|
+
id: n.id,
|
|
321
|
+
metadata: n.metadata,
|
|
322
|
+
status: n.status,
|
|
323
|
+
tx: s.tx,
|
|
324
|
+
result: s.result
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
class S {
|
|
307
328
|
constructor(e) {
|
|
308
329
|
a(this, "endpoint");
|
|
309
330
|
this.endpoint = e;
|
|
@@ -315,22 +336,23 @@ class M {
|
|
|
315
336
|
* @returns Promise resolving to connection details including ID, version, and encryption key
|
|
316
337
|
*/
|
|
317
338
|
async create(e, n) {
|
|
318
|
-
const r = await
|
|
339
|
+
const r = await p(e), s = {
|
|
319
340
|
metadata: n,
|
|
320
341
|
sealed: r.ciphertext
|
|
321
|
-
},
|
|
342
|
+
}, i = await fetch(this.endpoint, {
|
|
322
343
|
method: "POST",
|
|
323
344
|
headers: {
|
|
324
345
|
"Content-Type": "application/json"
|
|
325
346
|
},
|
|
326
|
-
body: JSON.stringify(
|
|
347
|
+
body: JSON.stringify(s)
|
|
327
348
|
});
|
|
328
|
-
if (!
|
|
329
|
-
throw new Error(`Failed to create connection: ${await
|
|
330
|
-
const o = await
|
|
349
|
+
if (!i.ok)
|
|
350
|
+
throw new Error(`Failed to create connection: ${await i.text()}`);
|
|
351
|
+
const o = await i.json();
|
|
331
352
|
return {
|
|
332
353
|
id: o.id,
|
|
333
354
|
version: o.version,
|
|
355
|
+
status: o.status,
|
|
334
356
|
metadata: n,
|
|
335
357
|
data: e,
|
|
336
358
|
key: r.key
|
|
@@ -343,26 +365,28 @@ class M {
|
|
|
343
365
|
* @param version Current version number
|
|
344
366
|
* @returns Promise resolving to updated connection details including new encryption key
|
|
345
367
|
*/
|
|
346
|
-
async update(e, n, r) {
|
|
347
|
-
const
|
|
348
|
-
sealed:
|
|
349
|
-
version: r
|
|
350
|
-
|
|
368
|
+
async update(e, n, r, s, i) {
|
|
369
|
+
const o = await p(n, i), c = {
|
|
370
|
+
sealed: o.ciphertext,
|
|
371
|
+
version: r,
|
|
372
|
+
status: s
|
|
373
|
+
}, h = await fetch(`${this.endpoint}/${e}`, {
|
|
351
374
|
method: "PATCH",
|
|
352
375
|
headers: {
|
|
353
376
|
"Content-Type": "application/json"
|
|
354
377
|
},
|
|
355
|
-
body: JSON.stringify(
|
|
378
|
+
body: JSON.stringify(c)
|
|
356
379
|
});
|
|
357
|
-
if (!
|
|
358
|
-
throw new Error(`Failed to update connection: ${await
|
|
359
|
-
const
|
|
380
|
+
if (!h.ok)
|
|
381
|
+
throw new Error(`Failed to update connection: ${await h.text()}`);
|
|
382
|
+
const d = await h.json();
|
|
360
383
|
return {
|
|
361
|
-
id:
|
|
362
|
-
metadata:
|
|
363
|
-
version:
|
|
384
|
+
id: d.id,
|
|
385
|
+
metadata: d.metadata,
|
|
386
|
+
version: d.version,
|
|
387
|
+
status: d.status,
|
|
364
388
|
data: n,
|
|
365
|
-
key:
|
|
389
|
+
key: o.key
|
|
366
390
|
};
|
|
367
391
|
}
|
|
368
392
|
/**
|
|
@@ -377,14 +401,15 @@ class M {
|
|
|
377
401
|
});
|
|
378
402
|
if (!r.ok)
|
|
379
403
|
throw new Error(`Failed to get connection: ${await r.text()}`);
|
|
380
|
-
const
|
|
381
|
-
ciphertext:
|
|
404
|
+
const s = await r.json(), i = s.sealed[s.sealed.length - 1], o = await f({
|
|
405
|
+
ciphertext: i,
|
|
382
406
|
key: n
|
|
383
407
|
});
|
|
384
408
|
return {
|
|
385
|
-
id:
|
|
386
|
-
|
|
387
|
-
|
|
409
|
+
id: s.id,
|
|
410
|
+
status: s.status,
|
|
411
|
+
version: s.version,
|
|
412
|
+
metadata: s.metadata,
|
|
388
413
|
data: o,
|
|
389
414
|
key: n
|
|
390
415
|
};
|
|
@@ -401,7 +426,7 @@ class M {
|
|
|
401
426
|
throw new Error(`Failed to close connection: ${await n.text()}`);
|
|
402
427
|
}
|
|
403
428
|
}
|
|
404
|
-
class
|
|
429
|
+
class k {
|
|
405
430
|
/**
|
|
406
431
|
* Creates a new instance of the Notabene SDK
|
|
407
432
|
*
|
|
@@ -425,15 +450,15 @@ class S {
|
|
|
425
450
|
* @returns component URL
|
|
426
451
|
* @internal
|
|
427
452
|
*/
|
|
428
|
-
componentUrl(e, n, r,
|
|
429
|
-
const
|
|
430
|
-
|
|
431
|
-
const o =
|
|
453
|
+
componentUrl(e, n, r, s) {
|
|
454
|
+
const i = new URL(this.uxUrl);
|
|
455
|
+
i.pathname = e;
|
|
456
|
+
const o = R({
|
|
432
457
|
authToken: this.authToken,
|
|
433
458
|
value: n,
|
|
434
459
|
configuration: r
|
|
435
460
|
});
|
|
436
|
-
return
|
|
461
|
+
return i.hash = o, this.nodeUrl && i.searchParams.set("nodeUrl", this.nodeUrl), this.theme && i.searchParams.set("theme", JSON.stringify(this.theme)), this.locale && i.searchParams.set("locale", this.locale), s && (s.callback && i.searchParams.set("callback_url", s.callback), s.redirectUri && i.searchParams.set("redirect_uri", s.redirectUri)), i.toString();
|
|
437
462
|
}
|
|
438
463
|
/**
|
|
439
464
|
* Creates a new embedded component
|
|
@@ -445,9 +470,9 @@ class S {
|
|
|
445
470
|
* @returns A new EmbeddedComponent instance
|
|
446
471
|
* @internal
|
|
447
472
|
*/
|
|
448
|
-
createComponent(e, n, r,
|
|
449
|
-
return new
|
|
450
|
-
this.componentUrl(e, n, r,
|
|
473
|
+
createComponent(e, n, r, s) {
|
|
474
|
+
return new x(
|
|
475
|
+
this.componentUrl(e, n, r, s),
|
|
451
476
|
n,
|
|
452
477
|
r
|
|
453
478
|
);
|
|
@@ -523,16 +548,17 @@ class S {
|
|
|
523
548
|
export {
|
|
524
549
|
A as AgentType,
|
|
525
550
|
l as CMType,
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
551
|
+
S as ConnectionManager,
|
|
552
|
+
x as EmbeddedComponent,
|
|
553
|
+
N as ErrorIdentifierCode,
|
|
554
|
+
E as HMType,
|
|
555
|
+
y as PersonType,
|
|
531
556
|
b as ProofStatus,
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
557
|
+
U as ProofTypes,
|
|
558
|
+
I as Status,
|
|
559
|
+
L as VASPSearchControl,
|
|
560
|
+
C as ValidationSections,
|
|
536
561
|
O as decodeFragmentToObject,
|
|
537
|
-
|
|
562
|
+
k as default,
|
|
563
|
+
M as getRefreshResult
|
|
538
564
|
};
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"author": "Notabene <developers@notabene.id>",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"packageManager": "yarn@4.5.1",
|
|
13
|
-
"version": "2.9.0-next.
|
|
13
|
+
"version": "2.9.0-next.2",
|
|
14
14
|
"source": "src/notabene.ts",
|
|
15
15
|
"main": "dist/cjs/notabene.cjs",
|
|
16
16
|
"module": "dist/esm/notabene.js",
|
package/src/notabene.ts
CHANGED
|
@@ -39,6 +39,7 @@ import type {
|
|
|
39
39
|
NotabeneAsset,
|
|
40
40
|
OwnershipProof,
|
|
41
41
|
Ready,
|
|
42
|
+
RefreshSource,
|
|
42
43
|
ResizeRequest,
|
|
43
44
|
ScreenshotProof,
|
|
44
45
|
SignatureProof,
|
|
@@ -75,9 +76,12 @@ import { decodeFragmentToObject, encodeObjectToFragment } from './utils/urls';
|
|
|
75
76
|
export { default as EmbeddedComponent } from './components/EmbeddedComponent';
|
|
76
77
|
export {
|
|
77
78
|
ConnectionManager,
|
|
79
|
+
getRefreshResult,
|
|
78
80
|
type ConnectionData,
|
|
79
81
|
type ConnectionMetadata,
|
|
80
82
|
type ConnectionResponse,
|
|
83
|
+
type ConnectionResult,
|
|
84
|
+
type ConnectionStatus,
|
|
81
85
|
type TransactionType,
|
|
82
86
|
} from './utils/connections';
|
|
83
87
|
export {
|
|
@@ -134,6 +138,7 @@ export type {
|
|
|
134
138
|
NotabeneAsset,
|
|
135
139
|
OwnershipProof,
|
|
136
140
|
Ready,
|
|
141
|
+
RefreshSource,
|
|
137
142
|
ResizeRequest,
|
|
138
143
|
ScreenshotProof,
|
|
139
144
|
SignatureProof,
|
|
@@ -68,6 +68,7 @@ describe('ConnectionManager', () => {
|
|
|
68
68
|
const mockResponse = {
|
|
69
69
|
id: 'test-id',
|
|
70
70
|
version: 1,
|
|
71
|
+
status: 'active',
|
|
71
72
|
metadata,
|
|
72
73
|
sealed: ['encrypted-data'],
|
|
73
74
|
};
|
|
@@ -92,6 +93,7 @@ describe('ConnectionManager', () => {
|
|
|
92
93
|
expect(result).toEqual({
|
|
93
94
|
id: mockResponse.id,
|
|
94
95
|
metadata: mockResponse.metadata,
|
|
96
|
+
status: mockResponse.status,
|
|
95
97
|
version: mockResponse.version,
|
|
96
98
|
data: request,
|
|
97
99
|
key: expect.any(String),
|
|
@@ -124,6 +126,9 @@ describe('ConnectionManager', () => {
|
|
|
124
126
|
|
|
125
127
|
describe('update', () => {
|
|
126
128
|
it('should successfully update an existing connection', async () => {
|
|
129
|
+
const testData = { requestId: 'test-123' };
|
|
130
|
+
const sealed = await seal(testData);
|
|
131
|
+
|
|
127
132
|
await fc.assert(
|
|
128
133
|
fc.asyncProperty(
|
|
129
134
|
fc.uuid(),
|
|
@@ -134,8 +139,9 @@ describe('ConnectionManager', () => {
|
|
|
134
139
|
const mockResponse = {
|
|
135
140
|
id,
|
|
136
141
|
metadata: arbConnectionMetadata,
|
|
142
|
+
status: 'completed',
|
|
137
143
|
version: version + 1,
|
|
138
|
-
sealed: [
|
|
144
|
+
sealed: [sealed.ciphertext],
|
|
139
145
|
};
|
|
140
146
|
|
|
141
147
|
fetchMock.mockResolvedValueOnce({
|
|
@@ -143,7 +149,13 @@ describe('ConnectionManager', () => {
|
|
|
143
149
|
json: async () => mockResponse,
|
|
144
150
|
});
|
|
145
151
|
|
|
146
|
-
const result = await manager.update(
|
|
152
|
+
const result = await manager.update(
|
|
153
|
+
id,
|
|
154
|
+
request,
|
|
155
|
+
version,
|
|
156
|
+
'completed',
|
|
157
|
+
sealed.key,
|
|
158
|
+
);
|
|
147
159
|
|
|
148
160
|
// Verify fetch was called correctly
|
|
149
161
|
expect(fetchMock).toHaveBeenCalledWith(`${testEndpoint}/${id}`, {
|
|
@@ -158,16 +170,19 @@ describe('ConnectionManager', () => {
|
|
|
158
170
|
expect(result).toEqual({
|
|
159
171
|
id: mockResponse.id,
|
|
160
172
|
version: mockResponse.version,
|
|
173
|
+
status: mockResponse.status,
|
|
161
174
|
metadata: mockResponse.metadata,
|
|
162
175
|
data: request,
|
|
163
|
-
key:
|
|
176
|
+
key: sealed.key,
|
|
164
177
|
});
|
|
165
178
|
},
|
|
166
179
|
),
|
|
167
180
|
);
|
|
168
181
|
});
|
|
169
182
|
|
|
170
|
-
it('should throw error on failed update', async () => {
|
|
183
|
+
it('should throw error on failed update due to invalid key', async () => {
|
|
184
|
+
const { key: newKey } = await seal('testData');
|
|
185
|
+
|
|
171
186
|
await fc.assert(
|
|
172
187
|
fc.asyncProperty(
|
|
173
188
|
fc.uuid(),
|
|
@@ -180,9 +195,9 @@ describe('ConnectionManager', () => {
|
|
|
180
195
|
text: async () => 'Update failed',
|
|
181
196
|
});
|
|
182
197
|
|
|
183
|
-
await expect(
|
|
184
|
-
|
|
185
|
-
);
|
|
198
|
+
await expect(
|
|
199
|
+
manager.update(id, request, version, 'active', newKey),
|
|
200
|
+
).rejects.toThrow('Failed to update connection');
|
|
186
201
|
},
|
|
187
202
|
),
|
|
188
203
|
);
|
|
@@ -201,6 +216,7 @@ describe('ConnectionManager', () => {
|
|
|
201
216
|
const mockResponse = {
|
|
202
217
|
id,
|
|
203
218
|
version: 1,
|
|
219
|
+
status: 'active',
|
|
204
220
|
metadata: arbConnectionMetadata,
|
|
205
221
|
sealed: [sealed.ciphertext], // Use the real ciphertext
|
|
206
222
|
};
|
|
@@ -221,6 +237,7 @@ describe('ConnectionManager', () => {
|
|
|
221
237
|
expect(result).toEqual({
|
|
222
238
|
id: mockResponse.id,
|
|
223
239
|
version: mockResponse.version,
|
|
240
|
+
status: mockResponse.status,
|
|
224
241
|
metadata: mockResponse.metadata,
|
|
225
242
|
data: testData, // Should match our original test data
|
|
226
243
|
key: sealed.key,
|
package/src/utils/connections.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ComponentRequest,
|
|
3
|
+
RefreshSource,
|
|
4
|
+
TransactionOptions,
|
|
5
|
+
TransactionResponse,
|
|
6
|
+
UUID,
|
|
7
|
+
} from '../types';
|
|
2
8
|
import { seal, unseal } from './encryption';
|
|
3
9
|
|
|
4
10
|
export type TransactionType = 'withdraw' | 'deposit';
|
|
11
|
+
export type ConnectionStatus = 'active' | 'completed' | 'closed';
|
|
5
12
|
export interface ConnectionData<T extends ComponentRequest> {
|
|
6
13
|
tx: T;
|
|
7
14
|
authToken?: string;
|
|
8
15
|
txOptions?: TransactionOptions;
|
|
16
|
+
result?: TransactionResponse<T>;
|
|
9
17
|
}
|
|
10
18
|
|
|
11
19
|
export interface ConnectionMetadata {
|
|
@@ -16,11 +24,55 @@ export interface ConnectionMetadata {
|
|
|
16
24
|
export interface ConnectionResponse<T extends ComponentRequest> {
|
|
17
25
|
id: UUID;
|
|
18
26
|
version: number;
|
|
27
|
+
status: ConnectionStatus;
|
|
19
28
|
metadata: ConnectionMetadata;
|
|
20
29
|
data: ConnectionData<T>;
|
|
21
30
|
key: string;
|
|
22
31
|
}
|
|
23
32
|
|
|
33
|
+
export interface ConnectionResult<T extends ComponentRequest> {
|
|
34
|
+
id: UUID;
|
|
35
|
+
metadata: ConnectionMetadata;
|
|
36
|
+
status: ConnectionStatus;
|
|
37
|
+
tx: T;
|
|
38
|
+
result?: TransactionResponse<T>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function getRefreshResult<T extends ComponentRequest>(
|
|
42
|
+
refreshSource: RefreshSource,
|
|
43
|
+
): Promise<ConnectionResult<T>> {
|
|
44
|
+
const response = await fetch(refreshSource.url, {
|
|
45
|
+
method: 'GET',
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
throw new Error(`Failed to get connection: ${await response.text()}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const result = await response.json();
|
|
53
|
+
|
|
54
|
+
if (!result.sealed) {
|
|
55
|
+
throw new Error('No data found');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Get the latest sealed data
|
|
59
|
+
const latestSealed = result.sealed[result.sealed.length - 1];
|
|
60
|
+
|
|
61
|
+
// Decrypt the data
|
|
62
|
+
const data = await unseal<ConnectionData<T>>({
|
|
63
|
+
ciphertext: latestSealed,
|
|
64
|
+
key: refreshSource.key,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
id: result.id,
|
|
69
|
+
metadata: result.metadata,
|
|
70
|
+
status: result.status,
|
|
71
|
+
tx: data.tx,
|
|
72
|
+
result: data.result,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
24
76
|
/**
|
|
25
77
|
* Manages encrypted connections using Cloudflare Durable Objects
|
|
26
78
|
*/
|
|
@@ -68,6 +120,7 @@ export class ConnectionManager {
|
|
|
68
120
|
return {
|
|
69
121
|
id: result.id,
|
|
70
122
|
version: result.version,
|
|
123
|
+
status: result.status,
|
|
71
124
|
metadata: metadata,
|
|
72
125
|
data: data,
|
|
73
126
|
key: sealed.key,
|
|
@@ -85,14 +138,17 @@ export class ConnectionManager {
|
|
|
85
138
|
id: UUID,
|
|
86
139
|
data: ConnectionData<T>,
|
|
87
140
|
version: number,
|
|
141
|
+
status: ConnectionStatus,
|
|
142
|
+
key: string,
|
|
88
143
|
): Promise<ConnectionResponse<T>> {
|
|
89
144
|
// Encrypt the new data
|
|
90
|
-
const sealed = await seal(data);
|
|
145
|
+
const sealed = await seal(data, key);
|
|
91
146
|
|
|
92
147
|
// Prepare the request body
|
|
93
148
|
const body = {
|
|
94
149
|
sealed: sealed.ciphertext,
|
|
95
150
|
version,
|
|
151
|
+
status,
|
|
96
152
|
};
|
|
97
153
|
|
|
98
154
|
// Update the connection
|
|
@@ -114,6 +170,7 @@ export class ConnectionManager {
|
|
|
114
170
|
id: result.id,
|
|
115
171
|
metadata: result.metadata,
|
|
116
172
|
version: result.version,
|
|
173
|
+
status: result.status,
|
|
117
174
|
data: data,
|
|
118
175
|
key: sealed.key,
|
|
119
176
|
};
|
|
@@ -151,6 +208,7 @@ export class ConnectionManager {
|
|
|
151
208
|
|
|
152
209
|
return {
|
|
153
210
|
id: result.id,
|
|
211
|
+
status: result.status,
|
|
154
212
|
version: result.version,
|
|
155
213
|
metadata: result.metadata,
|
|
156
214
|
data,
|
package/src/utils/encryption.ts
CHANGED
|
@@ -14,13 +14,15 @@ export interface Sealed {
|
|
|
14
14
|
* @param data Data to encrypt
|
|
15
15
|
* @returns Promise resolving to a Sealed object containing ciphertext and key
|
|
16
16
|
*/
|
|
17
|
-
export async function seal<T>(data: T): Promise<Sealed> {
|
|
17
|
+
export async function seal<T>(data: T, existingKey?: string): Promise<Sealed> {
|
|
18
18
|
// Convert the object to a JSON string
|
|
19
19
|
const plaintext = JSON.stringify(data);
|
|
20
20
|
const encoder = new TextEncoder();
|
|
21
21
|
|
|
22
|
-
//
|
|
23
|
-
const rawKey =
|
|
22
|
+
// Restore or generate a random encryption key
|
|
23
|
+
const rawKey = existingKey
|
|
24
|
+
? base64ToUint8Array(existingKey)
|
|
25
|
+
: crypto.getRandomValues(new Uint8Array(32));
|
|
24
26
|
const key = await crypto.subtle.importKey(
|
|
25
27
|
'raw',
|
|
26
28
|
rawKey,
|