Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@nimiq/accounts-client

Package Overview
Dependencies
Maintainers
8
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nimiq/accounts-client - npm Package Compare versions

Comparing version 0.1.3 to 0.2.0

64

dist/AccountsClient.es.js

@@ -1,2 +0,2 @@

import { RedirectRpcClient, PostMessageRpcClient, RandomUtils, UrlRpcEncoder, ReceiveOnlyPostMessageRpcClient } from '@nimiq/rpc';
import { PostMessageRpcClient, RedirectRpcClient } from '@nimiq/rpc';

@@ -43,8 +43,7 @@ class RequestBehavior {

const state = Object.assign({}, this._localState, { __command: command });
console.log('state', state);
client.callAndSaveLocalState(this._returnUrl, JSON.stringify(state), command, ...args);
client.callAndSaveLocalState(this._returnUrl, state, command, ...args);
}
}
class UrlEncodedPopupBehavior extends RequestBehavior {
constructor(options = UrlEncodedPopupBehavior.DEFAULT_OPTIONS) {
class PopupRequestBehavior extends RequestBehavior {
constructor(options = PopupRequestBehavior.DEFAULT_OPTIONS) {
super(BehaviorType.POPUP);

@@ -55,17 +54,14 @@ this._options = options;

const origin = RequestBehavior.getAllowedOrigin(endpoint);
const id = RandomUtils.generateRandomId();
const url = UrlRpcEncoder.prepareRedirectInvocation(endpoint, id, '<postMessage>', command, args);
const popup = this.createPopup(url);
const client = new ReceiveOnlyPostMessageRpcClient(popup, origin, id);
const popup = this.createPopup(endpoint);
const client = new PostMessageRpcClient(popup, origin);
await client.init();
try {
const result = await client.listenFor(command);
client.close();
popup.close();
return result;
return await client.callAndPersist(command, ...args);
}
catch (e) {
throw e;
}
finally {
client.close();
popup.close();
throw e;
}

@@ -81,3 +77,3 @@ }

}
UrlEncodedPopupBehavior.DEFAULT_OPTIONS = '';
PopupRequestBehavior.DEFAULT_OPTIONS = '';
class IFrameRequestBehavior extends RequestBehavior {

@@ -120,6 +116,2 @@ constructor() {

/**
* Sorted by context and alphabetically
*/
var RequestType;

@@ -136,5 +128,5 @@ (function (RequestType) {

RequestType["EXPORT"] = "export";
RequestType["CHANGE_PASSPHRASE"] = "change-passphrase";
RequestType["CHANGE_PASSWORD"] = "change-password";
RequestType["LOGOUT"] = "logout";
RequestType["ADD_ACCOUNT"] = "add-account";
RequestType["ADD_ADDRESS"] = "add-address";
RequestType["RENAME"] = "rename";

@@ -147,3 +139,3 @@ RequestType["CHOOSE_ADDRESS"] = "choose-address";

this._endpoint = endpoint;
this._defaultBehavior = defaultBehavior || new UrlEncodedPopupBehavior(`left=${window.innerWidth / 2 - 500},top=50,width=1000,height=900,location=yes,dependent=yes`);
this._defaultBehavior = defaultBehavior || new PopupRequestBehavior(`left=${window.innerWidth / 2 - 400},top=75,width=800,height=850,location=yes,dependent=yes`);
this._iframeBehavior = new IFrameRequestBehavior();

@@ -153,2 +145,15 @@ // Check for RPC results in the URL

}
static get DEFAULT_ENDPOINT() {
const originArray = location.origin.split('.');
originArray.shift();
const tld = originArray.join('.');
switch (tld) {
case 'nimiq.com':
return 'https://accounts.nimiq.com';
case 'nimiq-testnet.com':
return 'https://accounts.nimiq-testnet.com';
default:
return 'http://localhost:8080';
}
}
checkRedirectResponse() {

@@ -160,3 +165,3 @@ return this._redirectClient.init();

// State is always an object containing at least the __command property
(result, rpcId, state) => resolve(result, JSON.parse(state)), (error, rpcId, state) => reject && reject(error, JSON.parse(state)));
(result, rpcId, state) => resolve(result, state), (error, rpcId, state) => reject && reject(error, state));
}

@@ -187,7 +192,7 @@ onboard(request, requestBehavior = this._defaultBehavior) {

}
changePassphrase(request, requestBehavior = this._defaultBehavior) {
return this._request(requestBehavior, RequestType.CHANGE_PASSPHRASE, [request]);
changePassword(request, requestBehavior = this._defaultBehavior) {
return this._request(requestBehavior, RequestType.CHANGE_PASSWORD, [request]);
}
addAccount(request, requestBehavior = this._defaultBehavior) {
return this._request(requestBehavior, RequestType.ADD_ACCOUNT, [request]);
addAddress(request, requestBehavior = this._defaultBehavior) {
return this._request(requestBehavior, RequestType.ADD_ADDRESS, [request]);
}

@@ -201,3 +206,3 @@ rename(request, requestBehavior = this._defaultBehavior) {

migrate(requestBehavior = this._defaultBehavior) {
return this._request(requestBehavior, RequestType.MIGRATE, [{}]);
return this._request(requestBehavior, RequestType.MIGRATE, [{ appName: 'Accounts Client' }]);
}

@@ -218,6 +223,3 @@ /**

AccountsClient.RedirectRequestBehavior = RedirectRequestBehavior;
AccountsClient.DEFAULT_ENDPOINT = window.location.origin === 'https://safe-next.nimiq.com' ? 'https://accounts.nimiq.com'
: window.location.origin === 'https://safe-next.nimiq-testnet.com' ? 'https://accounts.nimiq-testnet.com'
: 'http://localhost:8080';
export default AccountsClient;

@@ -5,3 +5,3 @@ (function (global, factory) {

(global.AccountsClient = factory(global.rpc));
}(this, (function (Rpc) { 'use strict';
}(this, (function (rpc) { 'use strict';

@@ -45,11 +45,10 @@ class RequestBehavior {

const origin = RequestBehavior.getAllowedOrigin(endpoint);
const client = new Rpc.RedirectRpcClient(endpoint, origin);
const client = new rpc.RedirectRpcClient(endpoint, origin);
await client.init();
const state = Object.assign({}, this._localState, { __command: command });
console.log('state', state);
client.callAndSaveLocalState(this._returnUrl, JSON.stringify(state), command, ...args);
client.callAndSaveLocalState(this._returnUrl, state, command, ...args);
}
}
class UrlEncodedPopupBehavior extends RequestBehavior {
constructor(options = UrlEncodedPopupBehavior.DEFAULT_OPTIONS) {
class PopupRequestBehavior extends RequestBehavior {
constructor(options = PopupRequestBehavior.DEFAULT_OPTIONS) {
super(BehaviorType.POPUP);

@@ -60,17 +59,14 @@ this._options = options;

const origin = RequestBehavior.getAllowedOrigin(endpoint);
const id = Rpc.RandomUtils.generateRandomId();
const url = Rpc.UrlRpcEncoder.prepareRedirectInvocation(endpoint, id, '<postMessage>', command, args);
const popup = this.createPopup(url);
const client = new Rpc.ReceiveOnlyPostMessageRpcClient(popup, origin, id);
const popup = this.createPopup(endpoint);
const client = new rpc.PostMessageRpcClient(popup, origin);
await client.init();
try {
const result = await client.listenFor(command);
client.close();
popup.close();
return result;
return await client.callAndPersist(command, ...args);
}
catch (e) {
throw e;
}
finally {
client.close();
popup.close();
throw e;
}

@@ -86,3 +82,3 @@ }

}
UrlEncodedPopupBehavior.DEFAULT_OPTIONS = '';
PopupRequestBehavior.DEFAULT_OPTIONS = '';
class IFrameRequestBehavior extends RequestBehavior {

@@ -106,3 +102,3 @@ constructor() {

if (!this._client) {
this._client = new Rpc.PostMessageRpcClient(this._iframe.contentWindow, origin);
this._client = new rpc.PostMessageRpcClient(this._iframe.contentWindow, origin);
await this._client.init();

@@ -126,6 +122,2 @@ }

/**
* Sorted by context and alphabetically
*/
var RequestType;

@@ -142,5 +134,5 @@ (function (RequestType) {

RequestType["EXPORT"] = "export";
RequestType["CHANGE_PASSPHRASE"] = "change-passphrase";
RequestType["CHANGE_PASSWORD"] = "change-password";
RequestType["LOGOUT"] = "logout";
RequestType["ADD_ACCOUNT"] = "add-account";
RequestType["ADD_ADDRESS"] = "add-address";
RequestType["RENAME"] = "rename";

@@ -153,7 +145,20 @@ RequestType["CHOOSE_ADDRESS"] = "choose-address";

this._endpoint = endpoint;
this._defaultBehavior = defaultBehavior || new UrlEncodedPopupBehavior(`left=${window.innerWidth / 2 - 500},top=50,width=1000,height=900,location=yes,dependent=yes`);
this._defaultBehavior = defaultBehavior || new PopupRequestBehavior(`left=${window.innerWidth / 2 - 400},top=75,width=800,height=850,location=yes,dependent=yes`);
this._iframeBehavior = new IFrameRequestBehavior();
// Check for RPC results in the URL
this._redirectClient = new Rpc.RedirectRpcClient('', RequestBehavior.getAllowedOrigin(this._endpoint));
this._redirectClient = new rpc.RedirectRpcClient('', RequestBehavior.getAllowedOrigin(this._endpoint));
}
static get DEFAULT_ENDPOINT() {
const originArray = location.origin.split('.');
originArray.shift();
const tld = originArray.join('.');
switch (tld) {
case 'nimiq.com':
return 'https://accounts.nimiq.com';
case 'nimiq-testnet.com':
return 'https://accounts.nimiq-testnet.com';
default:
return 'http://localhost:8080';
}
}
checkRedirectResponse() {

@@ -165,3 +170,3 @@ return this._redirectClient.init();

// State is always an object containing at least the __command property
(result, rpcId, state) => resolve(result, JSON.parse(state)), (error, rpcId, state) => reject && reject(error, JSON.parse(state)));
(result, rpcId, state) => resolve(result, state), (error, rpcId, state) => reject && reject(error, state));
}

@@ -192,7 +197,7 @@ onboard(request, requestBehavior = this._defaultBehavior) {

}
changePassphrase(request, requestBehavior = this._defaultBehavior) {
return this._request(requestBehavior, RequestType.CHANGE_PASSPHRASE, [request]);
changePassword(request, requestBehavior = this._defaultBehavior) {
return this._request(requestBehavior, RequestType.CHANGE_PASSWORD, [request]);
}
addAccount(request, requestBehavior = this._defaultBehavior) {
return this._request(requestBehavior, RequestType.ADD_ACCOUNT, [request]);
addAddress(request, requestBehavior = this._defaultBehavior) {
return this._request(requestBehavior, RequestType.ADD_ADDRESS, [request]);
}

@@ -206,3 +211,3 @@ rename(request, requestBehavior = this._defaultBehavior) {

migrate(requestBehavior = this._defaultBehavior) {
return this._request(requestBehavior, RequestType.MIGRATE, [{}]);
return this._request(requestBehavior, RequestType.MIGRATE, [{ appName: 'Accounts Client' }]);
}

@@ -223,5 +228,2 @@ /**

AccountsClient.RedirectRequestBehavior = RedirectRequestBehavior;
AccountsClient.DEFAULT_ENDPOINT = window.location.origin === 'https://safe-next.nimiq.com' ? 'https://accounts.nimiq.com'
: window.location.origin === 'https://safe-next.nimiq-testnet.com' ? 'https://accounts.nimiq-testnet.com'
: 'http://localhost:8080';

@@ -228,0 +230,0 @@ return AccountsClient;

@@ -1,1 +0,1 @@

class RandomUtils{static generateRandomId(){const e=new Uint32Array(1);return crypto.getRandomValues(e),e[0]}}var ResponseStatus;!function(e){e.OK="ok",e.ERROR="error"}(ResponseStatus||(ResponseStatus={}));const POSTMESSAGE_RETURN_URL="<postMessage>";class Base64{static byteLength(e){const[t,s]=Base64._getLengths(e);return Base64._byteLength(t,s)}static decode(e){Base64._initRevLookup();const[t,s]=Base64._getLengths(e),r=new Uint8Array(Base64._byteLength(t,s));let i=0;const n=s>0?t-4:t;let o=0;for(;o<n;o+=4){const t=Base64._revLookup[e.charCodeAt(o)]<<18|Base64._revLookup[e.charCodeAt(o+1)]<<12|Base64._revLookup[e.charCodeAt(o+2)]<<6|Base64._revLookup[e.charCodeAt(o+3)];r[i++]=t>>16&255,r[i++]=t>>8&255,r[i++]=255&t}if(2===s){const t=Base64._revLookup[e.charCodeAt(o)]<<2|Base64._revLookup[e.charCodeAt(o+1)]>>4;r[i++]=255&t}if(1===s){const t=Base64._revLookup[e.charCodeAt(o)]<<10|Base64._revLookup[e.charCodeAt(o+1)]<<4|Base64._revLookup[e.charCodeAt(o+2)]>>2;r[i++]=t>>8&255,r[i]=255&t}return r}static encode(e){const t=e.length,s=t%3,r=[];for(let i=0,n=t-s;i<n;i+=16383)r.push(Base64._encodeChunk(e,i,i+16383>n?n:i+16383));if(1===s){const s=e[t-1];r.push(Base64._lookup[s>>2]+Base64._lookup[s<<4&63]+"==")}else if(2===s){const s=(e[t-2]<<8)+e[t-1];r.push(Base64._lookup[s>>10]+Base64._lookup[s>>4&63]+Base64._lookup[s<<2&63]+"=")}return r.join("")}static encodeUrl(e){return Base64.encode(e).replace(/\//g,"_").replace(/\+/g,"-").replace(/=/g,".")}static decodeUrl(e){return Base64.decode(e.replace(/_/g,"/").replace(/-/g,"+").replace(/\./g,"="))}static _initRevLookup(){if(0===Base64._revLookup.length){Base64._revLookup=[];for(let e=0,t=Base64._lookup.length;e<t;e++)Base64._revLookup[Base64._lookup.charCodeAt(e)]=e;Base64._revLookup["-".charCodeAt(0)]=62,Base64._revLookup["_".charCodeAt(0)]=63}}static _getLengths(e){const t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");let s=e.indexOf("=");return-1===s&&(s=t),[s,s===t?0:4-s%4]}static _byteLength(e,t){return 3*(e+t)/4-t}static _tripletToBase64(e){return Base64._lookup[e>>18&63]+Base64._lookup[e>>12&63]+Base64._lookup[e>>6&63]+Base64._lookup[63&e]}static _encodeChunk(e,t,s){const r=[];for(let i=t;i<s;i+=3){const t=(e[i]<<16&16711680)+(e[i+1]<<8&65280)+(255&e[i+2]);r.push(Base64._tripletToBase64(t))}return r.join("")}}var ExtraJSONTypes,BehaviorType,RequestType;Base64._lookup="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",Base64._revLookup=[],function(e){e[e.UINT8_ARRAY=0]="UINT8_ARRAY"}(ExtraJSONTypes||(ExtraJSONTypes={}));class JSONUtils{static stringify(e){return JSON.stringify(e,JSONUtils._jsonifyType)}static parse(e){return JSON.parse(e,JSONUtils._parseType)}static _parseType(e,t){if(t&&t.hasOwnProperty&&t.hasOwnProperty(JSONUtils.TYPE_SYMBOL)&&t.hasOwnProperty(JSONUtils.VALUE_SYMBOL))switch(t[JSONUtils.TYPE_SYMBOL]){case ExtraJSONTypes.UINT8_ARRAY:return Base64.decode(t[JSONUtils.VALUE_SYMBOL])}return t}static _jsonifyType(e,t){return t instanceof Uint8Array?JSONUtils._typedObject(ExtraJSONTypes.UINT8_ARRAY,Base64.encode(t)):t}static _typedObject(e,t){const s={};return s[JSONUtils.TYPE_SYMBOL]=e,s[JSONUtils.VALUE_SYMBOL]=t,s}}JSONUtils.TYPE_SYMBOL="__",JSONUtils.VALUE_SYMBOL="v";class RequestIdStorage{constructor(e=!0){this._store=e?window.sessionStorage:null,this._validIds=new Map,e&&this._restoreIds()}static _decodeIds(e){const t=JSONUtils.parse(e),s=new Map;for(const e of Object.keys(t)){const r=parseInt(e,10);s.set(isNaN(r)?e:r,t[e])}return s}has(e){return this._validIds.has(e)}getCommand(e){const t=this._validIds.get(e);return t?t[0]:null}getState(e){const t=this._validIds.get(e);return t?t[1]:null}add(e,t,s=null){this._validIds.set(e,[t,s]),this._storeIds()}remove(e){this._validIds.delete(e),this._storeIds()}clear(){this._validIds.clear(),this._store&&this._store.removeItem(RequestIdStorage.KEY)}_encodeIds(){const e=Object.create(null);for(const[t,s]of this._validIds)e[t]=s;return JSONUtils.stringify(e)}_restoreIds(){const e=this._store.getItem(RequestIdStorage.KEY);e&&(this._validIds=RequestIdStorage._decodeIds(e))}_storeIds(){this._store&&this._store.setItem(RequestIdStorage.KEY,this._encodeIds())}}RequestIdStorage.KEY="rpcRequests";class UrlRpcEncoder{static receiveRedirectCommand(e){if(!document.referrer)return null;const t=new URLSearchParams(e.search),s=new URL(document.referrer);if(!t.has("command"))return null;if(!t.has("id"))return null;if(!t.has("returnURL"))return null;const r=t.get("returnURL")===POSTMESSAGE_RETURN_URL&&window.opener;if(!r){if(new URL(t.get("returnURL")).origin!==s.origin)return null}let i=[];if(t.has("args"))try{i=JSONUtils.parse(t.get("args"))}catch(e){}return i=Array.isArray(i)?i:[],{origin:s.origin,data:{id:parseInt(t.get("id"),10),command:t.get("command"),args:i},returnURL:t.get("returnURL"),source:r?window.opener:null}}static receiveRedirectResponse(e){if(!document.referrer)return null;const t=new URLSearchParams(e.search),s=new URL(document.referrer);if(!t.has("status"))return null;if(!t.has("id"))return null;if(!t.has("result"))return null;const r=JSONUtils.parse(t.get("result")),i=t.get("status")===ResponseStatus.OK?ResponseStatus.OK:ResponseStatus.ERROR;return{origin:s.origin,data:{id:parseInt(t.get("id"),10),status:i,result:r}}}static prepareRedirectReply(e,t,s){const r=new URLSearchParams;return r.set("status",t),r.set("result",JSONUtils.stringify(s)),r.set("id",e.id.toString()),`${e.returnURL}${new URL(e.returnURL).search.length>0?"&":"?"}${r.toString()}`}static prepareRedirectInvocation(e,t,s,r,i){const n=new URLSearchParams;return n.set("id",t.toString()),n.set("returnURL",s),n.set("command",r),Array.isArray(i)&&n.set("args",JSONUtils.stringify(i)),`${e}?${n.toString()}`}}class RpcClient{constructor(e,t=!1){this._allowedOrigin=e,this._waitingRequests=new RequestIdStorage(t),this._responseHandlers=new Map}onResponse(e,t,s){this._responseHandlers.set(e,{resolve:t,reject:s})}_receive(e){if(!e.data||!e.data.status||!e.data.id||"*"!==this._allowedOrigin&&e.origin!==this._allowedOrigin)return;const t=e.data,s=this._getCallback(t.id),r=this._waitingRequests.getState(t.id);if(s){if(console.debug("RpcClient RECEIVE",t),t.status===ResponseStatus.OK)s.resolve(t.result,t.id,r);else if(t.status===ResponseStatus.ERROR){const e=new Error(t.result.message);t.result.stack&&(e.stack=t.result.stack),t.result.name&&(e.name=t.result.name),s.reject(e,t.id,r)}}else console.warn("Unknown RPC response:",t)}_getCallback(e){if(this._responseHandlers.has(e))return this._responseHandlers.get(e);{const t=this._waitingRequests.getCommand(e);if(t)return this._responseHandlers.get(t)}}}class PostMessageRpcClient extends RpcClient{constructor(e,t){super(t),this._target=e,this._connected=!1,this._receiveListener=this._receive.bind(this)}async init(){await this._connect(),window.addEventListener("message",this._receiveListener)}async call(e,...t){if(!this._connected)throw new Error("Client is not connected, call init first");return new Promise((s,r)=>{const i={command:e,args:t,id:RandomUtils.generateRandomId()};this._responseHandlers.set(i.id,{resolve:s,reject:r}),this._waitingRequests.add(i.id,e);const n=()=>{this._target.closed&&r(new Error("Window was closed")),setTimeout(n,500)};setTimeout(n,500),console.debug("RpcClient REQUEST",e,t),this._target.postMessage(i,this._allowedOrigin)})}close(){window.removeEventListener("message",this._receiveListener),this._connected=!1}_connect(){return new Promise((e,t)=>{const s=t=>{const{source:r,origin:i,data:n}=t;if(r===this._target&&n.status===ResponseStatus.OK&&"pong"===n.result&&1===n.id&&("*"===this._allowedOrigin||i===this._allowedOrigin)){if(n.result.stack){const e=new Error(n.result.message);e.stack=n.result.stack,n.result.name&&(e.name=n.result.name),console.error(e)}window.removeEventListener("message",s),this._connected=!0,console.log("RpcClient: Connection established"),window.addEventListener("message",this._receiveListener),e(!0)}};window.addEventListener("message",s);let r=0;const i=setTimeout(()=>{window.removeEventListener("message",s),clearTimeout(r),t(new Error("Connection timeout"))},1e4),n=()=>{if(this._connected)clearTimeout(i);else{try{this._target.postMessage({command:"ping",id:1},this._allowedOrigin)}catch(e){console.error(`postMessage failed: ${e}`)}r=setTimeout(n,1e3)}};r=setTimeout(n,100)})}}class ReceiveOnlyPostMessageRpcClient extends PostMessageRpcClient{constructor(e,t,s){super(e,t),this._requestId=s}async init(){window.addEventListener("message",this._receiveListener)}async listenFor(e){return new Promise((t,s)=>{this._responseHandlers.set(this._requestId,{resolve:t,reject:s}),this._waitingRequests.add(this._requestId,e);const r=()=>{this._target.closed&&s(new Error("Window was closed")),setTimeout(r,500)};setTimeout(r,500)})}}class RedirectRpcClient extends RpcClient{constructor(e,t){super(t,!0),this._target=e}async init(){const e=UrlRpcEncoder.receiveRedirectResponse(window.location);e?this._receive(e):UrlRpcEncoder.receiveRedirectCommand(window.location)||this._rejectOnBack()}close(){}call(e,t,...s){this.callAndSaveLocalState(e,null,t,...s)}callAndSaveLocalState(e,t,s,...r){const i=RandomUtils.generateRandomId(),n=UrlRpcEncoder.prepareRedirectInvocation(this._target,i,e,s,r);this._waitingRequests.add(i,s,t),history.replaceState({rpcRequestId:i},document.title),console.debug("RpcClient REQUEST",s,r),window.location.href=n}_rejectOnBack(){if(history.state&&history.state.rpcRequestId){const e=history.state.rpcRequestId,t=this._getCallback(e),s=this._waitingRequests.getState(e);if(t){console.debug("RpcClient BACK");const r=new Error("Request aborted");t.reject(r,e,s)}}}}class RequestBehavior{static getAllowedOrigin(e){return new URL(e).origin}constructor(e){this._type=e}async request(e,t,s){throw new Error("Not implemented")}get type(){return this._type}}!function(e){e[e.REDIRECT=0]="REDIRECT",e[e.POPUP=1]="POPUP",e[e.IFRAME=2]="IFRAME"}(BehaviorType||(BehaviorType={}));class RedirectRequestBehavior extends RequestBehavior{static withLocalState(e){return new RedirectRequestBehavior(void 0,e)}constructor(e,t){super(BehaviorType.REDIRECT);const s=window.location;if(this._returnUrl=e||`${s.origin}${s.pathname}`,this._localState=t||{},void 0!==this._localState.__command)throw new Error("Invalid localState: Property '__command' is reserved")}async request(e,t,s){const r=RequestBehavior.getAllowedOrigin(e),i=new RedirectRpcClient(e,r);await i.init();const n=Object.assign({},this._localState,{__command:t});console.log("state",n),i.callAndSaveLocalState(this._returnUrl,JSON.stringify(n),t,...s)}}class UrlEncodedPopupBehavior extends RequestBehavior{constructor(e=UrlEncodedPopupBehavior.DEFAULT_OPTIONS){super(BehaviorType.POPUP),this._options=e}async request(e,t,s){const r=RequestBehavior.getAllowedOrigin(e),i=RandomUtils.generateRandomId(),n=UrlRpcEncoder.prepareRedirectInvocation(e,i,"<postMessage>",t,s),o=this.createPopup(n),a=new ReceiveOnlyPostMessageRpcClient(o,r,i);await a.init();try{const e=await a.listenFor(t);return a.close(),o.close(),e}catch(e){throw a.close(),o.close(),e}}createPopup(e){const t=window.open(e,"NimiqAccounts",this._options);if(!t)throw new Error("Failed to open popup");return t}}UrlEncodedPopupBehavior.DEFAULT_OPTIONS="";class IFrameRequestBehavior extends RequestBehavior{constructor(){super(BehaviorType.IFRAME),this._iframe=null,this._client=null}async request(e,t,s){if(this._iframe&&this._iframe.src!==`${e}${IFrameRequestBehavior.IFRAME_PATH_SUFFIX}`)throw new Error("Accounts Manager iframe is already opened with another endpoint");const r=RequestBehavior.getAllowedOrigin(e);if(this._iframe||(this._iframe=await this.createIFrame(e)),!this._iframe.contentWindow)throw new Error(`IFrame contentWindow is ${typeof this._iframe.contentWindow}`);return this._client||(this._client=new PostMessageRpcClient(this._iframe.contentWindow,r),await this._client.init()),await this._client.call(t,...s)}async createIFrame(e){return new Promise((t,s)=>{const r=document.createElement("iframe");r.name="NimiqAccountsIFrame",r.style.display="none",document.body.appendChild(r),r.src=`${e}${IFrameRequestBehavior.IFRAME_PATH_SUFFIX}`,r.onload=(()=>t(r)),r.onerror=s})}}IFrameRequestBehavior.IFRAME_PATH_SUFFIX="/iframe.html",function(e){e.LIST="list",e.MIGRATE="migrate",e.CHECKOUT="checkout",e.SIGN_MESSAGE="sign-message",e.SIGN_TRANSACTION="sign-transaction",e.ONBOARD="onboard",e.SIGNUP="signup",e.LOGIN="login",e.EXPORT="export",e.CHANGE_PASSPHRASE="change-passphrase",e.LOGOUT="logout",e.ADD_ACCOUNT="add-account",e.RENAME="rename",e.CHOOSE_ADDRESS="choose-address"}(RequestType||(RequestType={}));class AccountsClient{constructor(e=AccountsClient.DEFAULT_ENDPOINT,t){this._endpoint=e,this._defaultBehavior=t||new UrlEncodedPopupBehavior(`left=${window.innerWidth/2-500},top=50,width=1000,height=900,location=yes,dependent=yes`),this._iframeBehavior=new IFrameRequestBehavior,this._redirectClient=new RedirectRpcClient("",RequestBehavior.getAllowedOrigin(this._endpoint))}checkRedirectResponse(){return this._redirectClient.init()}on(e,t,s){this._redirectClient.onResponse(e,(e,s,r)=>t(e,JSON.parse(r)),(e,t,r)=>s&&s(e,JSON.parse(r)))}onboard(e,t=this._defaultBehavior){return this._request(t,RequestType.ONBOARD,[e])}signup(e,t=this._defaultBehavior){return this._request(t,RequestType.SIGNUP,[e])}login(e,t=this._defaultBehavior){return this._request(t,RequestType.LOGIN,[e])}chooseAddress(e,t=this._defaultBehavior){return this._request(t,RequestType.CHOOSE_ADDRESS,[e])}signTransaction(e,t=this._defaultBehavior){return this._request(t,RequestType.SIGN_TRANSACTION,[e])}checkout(e,t=this._defaultBehavior){return this._request(t,RequestType.CHECKOUT,[e])}logout(e,t=this._defaultBehavior){return this._request(t,RequestType.LOGOUT,[e])}export(e,t=this._defaultBehavior){return this._request(t,RequestType.EXPORT,[e])}changePassphrase(e,t=this._defaultBehavior){return this._request(t,RequestType.CHANGE_PASSPHRASE,[e])}addAccount(e,t=this._defaultBehavior){return this._request(t,RequestType.ADD_ACCOUNT,[e])}rename(e,t=this._defaultBehavior){return this._request(t,RequestType.RENAME,[e])}signMessage(e,t=this._defaultBehavior){return this._request(t,RequestType.SIGN_MESSAGE,[e])}migrate(e=this._defaultBehavior){return this._request(e,RequestType.MIGRATE,[{}])}list(e=this._iframeBehavior){return this._request(e,RequestType.LIST,[])}_request(e,t,s){return e.request(this._endpoint,t,s)}}AccountsClient.RequestType=RequestType,AccountsClient.RedirectRequestBehavior=RedirectRequestBehavior,AccountsClient.DEFAULT_ENDPOINT="https://safe-next.nimiq.com"===window.location.origin?"https://accounts.nimiq.com":"https://safe-next.nimiq-testnet.com"===window.location.origin?"https://accounts.nimiq-testnet.com":"http://localhost:8080";export default AccountsClient;
class RandomUtils{static generateRandomId(){const e=new Uint32Array(1);return crypto.getRandomValues(e),e[0]}}var ResponseStatus;!function(e){e.OK="ok",e.ERROR="error"}(ResponseStatus||(ResponseStatus={}));const POSTMESSAGE_RETURN_URL="<postMessage>";class Base64{static byteLength(e){const[t,s]=Base64._getLengths(e);return Base64._byteLength(t,s)}static decode(e){Base64._initRevLookup();const[t,s]=Base64._getLengths(e),r=new Uint8Array(Base64._byteLength(t,s));let i=0;const n=s>0?t-4:t;let o=0;for(;o<n;o+=4){const t=Base64._revLookup[e.charCodeAt(o)]<<18|Base64._revLookup[e.charCodeAt(o+1)]<<12|Base64._revLookup[e.charCodeAt(o+2)]<<6|Base64._revLookup[e.charCodeAt(o+3)];r[i++]=t>>16&255,r[i++]=t>>8&255,r[i++]=255&t}if(2===s){const t=Base64._revLookup[e.charCodeAt(o)]<<2|Base64._revLookup[e.charCodeAt(o+1)]>>4;r[i++]=255&t}if(1===s){const t=Base64._revLookup[e.charCodeAt(o)]<<10|Base64._revLookup[e.charCodeAt(o+1)]<<4|Base64._revLookup[e.charCodeAt(o+2)]>>2;r[i++]=t>>8&255,r[i]=255&t}return r}static encode(e){const t=e.length,s=t%3,r=[];for(let i=0,n=t-s;i<n;i+=16383)r.push(Base64._encodeChunk(e,i,i+16383>n?n:i+16383));if(1===s){const s=e[t-1];r.push(Base64._lookup[s>>2]+Base64._lookup[s<<4&63]+"==")}else if(2===s){const s=(e[t-2]<<8)+e[t-1];r.push(Base64._lookup[s>>10]+Base64._lookup[s>>4&63]+Base64._lookup[s<<2&63]+"=")}return r.join("")}static encodeUrl(e){return Base64.encode(e).replace(/\//g,"_").replace(/\+/g,"-").replace(/=/g,".")}static decodeUrl(e){return Base64.decode(e.replace(/_/g,"/").replace(/-/g,"+").replace(/\./g,"="))}static _initRevLookup(){if(0===Base64._revLookup.length){Base64._revLookup=[];for(let e=0,t=Base64._lookup.length;e<t;e++)Base64._revLookup[Base64._lookup.charCodeAt(e)]=e;Base64._revLookup["-".charCodeAt(0)]=62,Base64._revLookup["_".charCodeAt(0)]=63}}static _getLengths(e){const t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");let s=e.indexOf("=");return-1===s&&(s=t),[s,s===t?0:4-s%4]}static _byteLength(e,t){return 3*(e+t)/4-t}static _tripletToBase64(e){return Base64._lookup[e>>18&63]+Base64._lookup[e>>12&63]+Base64._lookup[e>>6&63]+Base64._lookup[63&e]}static _encodeChunk(e,t,s){const r=[];for(let i=t;i<s;i+=3){const t=(e[i]<<16&16711680)+(e[i+1]<<8&65280)+(255&e[i+2]);r.push(Base64._tripletToBase64(t))}return r.join("")}}var ExtraJSONTypes,BehaviorType,RequestType;Base64._lookup="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",Base64._revLookup=[],function(e){e[e.UINT8_ARRAY=0]="UINT8_ARRAY"}(ExtraJSONTypes||(ExtraJSONTypes={}));class JSONUtils{static stringify(e){return JSON.stringify(e,JSONUtils._jsonifyType)}static parse(e){return JSON.parse(e,JSONUtils._parseType)}static _parseType(e,t){if(t&&t.hasOwnProperty&&t.hasOwnProperty(JSONUtils.TYPE_SYMBOL)&&t.hasOwnProperty(JSONUtils.VALUE_SYMBOL))switch(t[JSONUtils.TYPE_SYMBOL]){case ExtraJSONTypes.UINT8_ARRAY:return Base64.decode(t[JSONUtils.VALUE_SYMBOL])}return t}static _jsonifyType(e,t){return t instanceof Uint8Array?JSONUtils._typedObject(ExtraJSONTypes.UINT8_ARRAY,Base64.encode(t)):t}static _typedObject(e,t){const s={};return s[JSONUtils.TYPE_SYMBOL]=e,s[JSONUtils.VALUE_SYMBOL]=t,s}}JSONUtils.TYPE_SYMBOL="__",JSONUtils.VALUE_SYMBOL="v";class RequestIdStorage{constructor(e=!0){this._store=e?window.sessionStorage:null,this._validIds=new Map,e&&this._restoreIds()}static _decodeIds(e){const t=JSONUtils.parse(e),s=new Map;for(const e of Object.keys(t)){const r=parseInt(e,10);s.set(isNaN(r)?e:r,t[e])}return s}has(e){return this._validIds.has(e)}getCommand(e){const t=this._validIds.get(e);return t?t[0]:null}getState(e){const t=this._validIds.get(e);return t?t[1]:null}add(e,t,s=null){this._validIds.set(e,[t,s]),this._storeIds()}remove(e){this._validIds.delete(e),this._storeIds()}clear(){this._validIds.clear(),this._store&&this._store.removeItem(RequestIdStorage.KEY)}_encodeIds(){const e=Object.create(null);for(const[t,s]of this._validIds)e[t]=s;return JSONUtils.stringify(e)}_restoreIds(){const e=this._store.getItem(RequestIdStorage.KEY);e&&(this._validIds=RequestIdStorage._decodeIds(e))}_storeIds(){this._store&&this._store.setItem(RequestIdStorage.KEY,this._encodeIds())}}RequestIdStorage.KEY="rpcRequests";class UrlRpcEncoder{static receiveRedirectCommand(e){if(!document.referrer)return null;const t=new URLSearchParams(e.search),s=new URL(document.referrer);if(!t.has("command"))return null;if(!t.has("id"))return null;if(!t.has("returnURL"))return null;const r=t.get("returnURL")===POSTMESSAGE_RETURN_URL&&(window.opener||window.parent);if(!r){if(new URL(t.get("returnURL")).origin!==s.origin)return null}let i=[];if(t.has("args"))try{i=JSONUtils.parse(t.get("args"))}catch(e){}return i=Array.isArray(i)?i:[],{origin:s.origin,data:{id:parseInt(t.get("id"),10),command:t.get("command"),args:i},returnURL:t.get("returnURL"),source:r?window.opener||window.parent:null}}static receiveRedirectResponse(e){if(!document.referrer)return null;const t=new URLSearchParams(e.search),s=new URL(document.referrer);if(!t.has("status"))return null;if(!t.has("id"))return null;if(!t.has("result"))return null;const r=JSONUtils.parse(t.get("result")),i=t.get("status")===ResponseStatus.OK?ResponseStatus.OK:ResponseStatus.ERROR;return{origin:s.origin,data:{id:parseInt(t.get("id"),10),status:i,result:r}}}static prepareRedirectReply(e,t,s){const r=new URL(e.returnURL),i=r.searchParams;return i.set("status",t),i.set("result",JSONUtils.stringify(s)),i.set("id",e.id.toString()),r.href}static prepareRedirectInvocation(e,t,s,r,i){const n=new URL(e),o=n.searchParams;return o.set("id",t.toString()),o.set("returnURL",s),o.set("command",r),Array.isArray(i)&&o.set("args",JSONUtils.stringify(i)),n.href}}class RpcClient{constructor(e,t=!1){this._allowedOrigin=e,this._waitingRequests=new RequestIdStorage(t),this._responseHandlers=new Map,this._preserveRequests=!1}onResponse(e,t,s){this._responseHandlers.set(e,{resolve:t,reject:s})}_receive(e){if(!e.data||!e.data.status||!e.data.id||"*"!==this._allowedOrigin&&e.origin!==this._allowedOrigin)return;const t=e.data,s=this._getCallback(t.id),r=this._waitingRequests.getState(t.id);if(s){if(this._preserveRequests||(this._waitingRequests.remove(t.id),this._responseHandlers.delete(t.id)),console.debug("RpcClient RECEIVE",t),t.status===ResponseStatus.OK)s.resolve(t.result,t.id,r);else if(t.status===ResponseStatus.ERROR){const e=new Error(t.result.message);t.result.stack&&(e.stack=t.result.stack),t.result.name&&(e.name=t.result.name),s.reject(e,t.id,r)}}else console.warn("Unknown RPC response:",t)}_getCallback(e){if(this._responseHandlers.has(e))return this._responseHandlers.get(e);{const t=this._waitingRequests.getCommand(e);if(t)return this._responseHandlers.get(t)}}}class PostMessageRpcClient extends RpcClient{constructor(e,t){super(t),this._serverCloseCheckInterval=-1,this._target=e,this._connectionState=0,this._receiveListener=this._receive.bind(this)}async init(){2!==this._connectionState&&(await this._connect(),window.addEventListener("message",this._receiveListener),-1===this._serverCloseCheckInterval&&(this._serverCloseCheckInterval=window.setInterval(()=>this._checkIfServerClosed(),300)))}async call(e,...t){return this._call({command:e,args:t,id:RandomUtils.generateRandomId()})}async callAndPersist(e,...t){return this._call({command:e,args:t,id:RandomUtils.generateRandomId(),persistInUrl:!0})}close(){this._connectionState=0,window.removeEventListener("message",this._receiveListener),window.clearInterval(this._serverCloseCheckInterval),this._serverCloseCheckInterval=-1;for(const[e,{reject:t}]of this._responseHandlers){const s=this._waitingRequests.getState(e);t("Connection was closed","number"==typeof e?e:void 0,s)}this._waitingRequests.clear(),this._responseHandlers.clear(),this._target&&this._target.closed&&(this._target=null)}_receive(e){e.source===this._target&&super._receive(e)}async _call(e){if(!this._target||this._target.closed)throw new Error("Connection was closed.");if(2!==this._connectionState)throw new Error("Client is not connected, call init first");return new Promise((t,s)=>{this._responseHandlers.set(e.id,{resolve:t,reject:s}),this._waitingRequests.add(e.id,e.command),console.debug("RpcClient REQUEST",e.command,e.args),this._target.postMessage(e,this._allowedOrigin)})}_connect(){if(2!==this._connectionState)return this._connectionState=1,new Promise((e,t)=>{const s=t=>{const{source:r,origin:i,data:n}=t;if(r===this._target&&n.status===ResponseStatus.OK&&"pong"===n.result&&1===n.id&&("*"===this._allowedOrigin||i===this._allowedOrigin)){if(n.result.stack){const e=new Error(n.result.message);e.stack=n.result.stack,n.result.name&&(e.name=n.result.name),console.error(e)}window.removeEventListener("message",s),this._connectionState=2,console.log("RpcClient: Connection established"),e(!0)}};window.addEventListener("message",s);const r=()=>{if(2!==this._connectionState){if(0===this._connectionState||this._checkIfServerClosed())return window.removeEventListener("message",s),void t(new Error("Connection was closed"));try{this._target.postMessage({command:"ping",id:1},this._allowedOrigin)}catch(e){console.error(`postMessage failed: ${e}`)}window.setTimeout(r,100)}};window.setTimeout(r,100)})}_checkIfServerClosed(){return!(this._target&&!this._target.closed)&&(this.close(),!0)}}class RedirectRpcClient extends RpcClient{constructor(e,t,s=!0){super(t,!0),this._target=e,this._preserveRequests=s}async init(){const e=UrlRpcEncoder.receiveRedirectResponse(window.location);e?this._receive(e):UrlRpcEncoder.receiveRedirectCommand(window.location)||this._rejectOnBack()}close(){}call(e,t,...s){this.callAndSaveLocalState(e,null,t,...s)}callAndSaveLocalState(e,t,s,...r){const i=RandomUtils.generateRandomId(),n=UrlRpcEncoder.prepareRedirectInvocation(this._target,i,e,s,r);this._waitingRequests.add(i,s,t),history.replaceState({rpcRequestId:i},document.title),console.debug("RpcClient REQUEST",s,r),window.location.href=n}_rejectOnBack(){if(history.state&&history.state.rpcRequestId){const e=history.state.rpcRequestId,t=this._getCallback(e),s=this._waitingRequests.getState(e);if(t){this._preserveRequests||(this._waitingRequests.remove(e),this._responseHandlers.delete(e)),console.debug("RpcClient BACK");const r=new Error("Request aborted");t.reject(r,e,s)}}}}class RequestBehavior{static getAllowedOrigin(e){return new URL(e).origin}constructor(e){this._type=e}async request(e,t,s){throw new Error("Not implemented")}get type(){return this._type}}!function(e){e[e.REDIRECT=0]="REDIRECT",e[e.POPUP=1]="POPUP",e[e.IFRAME=2]="IFRAME"}(BehaviorType||(BehaviorType={}));class RedirectRequestBehavior extends RequestBehavior{static withLocalState(e){return new RedirectRequestBehavior(void 0,e)}constructor(e,t){super(BehaviorType.REDIRECT);const s=window.location;if(this._returnUrl=e||`${s.origin}${s.pathname}`,this._localState=t||{},void 0!==this._localState.__command)throw new Error("Invalid localState: Property '__command' is reserved")}async request(e,t,s){const r=RequestBehavior.getAllowedOrigin(e),i=new RedirectRpcClient(e,r);await i.init();const n=Object.assign({},this._localState,{__command:t});i.callAndSaveLocalState(this._returnUrl,n,t,...s)}}class PopupRequestBehavior extends RequestBehavior{constructor(e=PopupRequestBehavior.DEFAULT_OPTIONS){super(BehaviorType.POPUP),this._options=e}async request(e,t,s){const r=RequestBehavior.getAllowedOrigin(e),i=this.createPopup(e),n=new PostMessageRpcClient(i,r);await n.init();try{return await n.callAndPersist(t,...s)}catch(e){throw e}finally{n.close(),i.close()}}createPopup(e){const t=window.open(e,"NimiqAccounts",this._options);if(!t)throw new Error("Failed to open popup");return t}}PopupRequestBehavior.DEFAULT_OPTIONS="";class IFrameRequestBehavior extends RequestBehavior{constructor(){super(BehaviorType.IFRAME),this._iframe=null,this._client=null}async request(e,t,s){if(this._iframe&&this._iframe.src!==`${e}${IFrameRequestBehavior.IFRAME_PATH_SUFFIX}`)throw new Error("Accounts Manager iframe is already opened with another endpoint");const r=RequestBehavior.getAllowedOrigin(e);if(this._iframe||(this._iframe=await this.createIFrame(e)),!this._iframe.contentWindow)throw new Error(`IFrame contentWindow is ${typeof this._iframe.contentWindow}`);return this._client||(this._client=new PostMessageRpcClient(this._iframe.contentWindow,r),await this._client.init()),await this._client.call(t,...s)}async createIFrame(e){return new Promise((t,s)=>{const r=document.createElement("iframe");r.name="NimiqAccountsIFrame",r.style.display="none",document.body.appendChild(r),r.src=`${e}${IFrameRequestBehavior.IFRAME_PATH_SUFFIX}`,r.onload=(()=>t(r)),r.onerror=s})}}IFrameRequestBehavior.IFRAME_PATH_SUFFIX="/iframe.html",function(e){e.LIST="list",e.MIGRATE="migrate",e.CHECKOUT="checkout",e.SIGN_MESSAGE="sign-message",e.SIGN_TRANSACTION="sign-transaction",e.ONBOARD="onboard",e.SIGNUP="signup",e.LOGIN="login",e.EXPORT="export",e.CHANGE_PASSWORD="change-password",e.LOGOUT="logout",e.ADD_ADDRESS="add-address",e.RENAME="rename",e.CHOOSE_ADDRESS="choose-address"}(RequestType||(RequestType={}));class AccountsClient{constructor(e=AccountsClient.DEFAULT_ENDPOINT,t){this._endpoint=e,this._defaultBehavior=t||new PopupRequestBehavior(`left=${window.innerWidth/2-400},top=75,width=800,height=850,location=yes,dependent=yes`),this._iframeBehavior=new IFrameRequestBehavior,this._redirectClient=new RedirectRpcClient("",RequestBehavior.getAllowedOrigin(this._endpoint))}static get DEFAULT_ENDPOINT(){const e=location.origin.split(".");switch(e.shift(),e.join(".")){case"nimiq.com":return"https://accounts.nimiq.com";case"nimiq-testnet.com":return"https://accounts.nimiq-testnet.com";default:return"http://localhost:8080"}}checkRedirectResponse(){return this._redirectClient.init()}on(e,t,s){this._redirectClient.onResponse(e,(e,s,r)=>t(e,r),(e,t,r)=>s&&s(e,r))}onboard(e,t=this._defaultBehavior){return this._request(t,RequestType.ONBOARD,[e])}signup(e,t=this._defaultBehavior){return this._request(t,RequestType.SIGNUP,[e])}login(e,t=this._defaultBehavior){return this._request(t,RequestType.LOGIN,[e])}chooseAddress(e,t=this._defaultBehavior){return this._request(t,RequestType.CHOOSE_ADDRESS,[e])}signTransaction(e,t=this._defaultBehavior){return this._request(t,RequestType.SIGN_TRANSACTION,[e])}checkout(e,t=this._defaultBehavior){return this._request(t,RequestType.CHECKOUT,[e])}logout(e,t=this._defaultBehavior){return this._request(t,RequestType.LOGOUT,[e])}export(e,t=this._defaultBehavior){return this._request(t,RequestType.EXPORT,[e])}changePassword(e,t=this._defaultBehavior){return this._request(t,RequestType.CHANGE_PASSWORD,[e])}addAddress(e,t=this._defaultBehavior){return this._request(t,RequestType.ADD_ADDRESS,[e])}rename(e,t=this._defaultBehavior){return this._request(t,RequestType.RENAME,[e])}signMessage(e,t=this._defaultBehavior){return this._request(t,RequestType.SIGN_MESSAGE,[e])}migrate(e=this._defaultBehavior){return this._request(e,RequestType.MIGRATE,[{appName:"Accounts Client"}])}list(e=this._iframeBehavior){return this._request(e,RequestType.LIST,[])}_request(e,t,s){return e.request(this._endpoint,t,s)}}AccountsClient.RequestType=RequestType,AccountsClient.RedirectRequestBehavior=RedirectRequestBehavior;export default AccountsClient;

@@ -1,1 +0,1 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.AccountsClient=t()}(this,function(){"use strict";class e{static generateRandomId(){const e=new Uint32Array(1);return crypto.getRandomValues(e),e[0]}}var t;!function(e){e.OK="ok",e.ERROR="error"}(t||(t={}));const s="<postMessage>";class r{static byteLength(e){const[t,s]=r._getLengths(e);return r._byteLength(t,s)}static decode(e){r._initRevLookup();const[t,s]=r._getLengths(e),n=new Uint8Array(r._byteLength(t,s));let i=0;const o=s>0?t-4:t;let a=0;for(;a<o;a+=4){const t=r._revLookup[e.charCodeAt(a)]<<18|r._revLookup[e.charCodeAt(a+1)]<<12|r._revLookup[e.charCodeAt(a+2)]<<6|r._revLookup[e.charCodeAt(a+3)];n[i++]=t>>16&255,n[i++]=t>>8&255,n[i++]=255&t}if(2===s){const t=r._revLookup[e.charCodeAt(a)]<<2|r._revLookup[e.charCodeAt(a+1)]>>4;n[i++]=255&t}if(1===s){const t=r._revLookup[e.charCodeAt(a)]<<10|r._revLookup[e.charCodeAt(a+1)]<<4|r._revLookup[e.charCodeAt(a+2)]>>2;n[i++]=t>>8&255,n[i]=255&t}return n}static encode(e){const t=e.length,s=t%3,n=[];for(let i=0,o=t-s;i<o;i+=16383)n.push(r._encodeChunk(e,i,i+16383>o?o:i+16383));if(1===s){const s=e[t-1];n.push(r._lookup[s>>2]+r._lookup[s<<4&63]+"==")}else if(2===s){const s=(e[t-2]<<8)+e[t-1];n.push(r._lookup[s>>10]+r._lookup[s>>4&63]+r._lookup[s<<2&63]+"=")}return n.join("")}static encodeUrl(e){return r.encode(e).replace(/\//g,"_").replace(/\+/g,"-").replace(/=/g,".")}static decodeUrl(e){return r.decode(e.replace(/_/g,"/").replace(/-/g,"+").replace(/\./g,"="))}static _initRevLookup(){if(0===r._revLookup.length){r._revLookup=[];for(let e=0,t=r._lookup.length;e<t;e++)r._revLookup[r._lookup.charCodeAt(e)]=e;r._revLookup["-".charCodeAt(0)]=62,r._revLookup["_".charCodeAt(0)]=63}}static _getLengths(e){const t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");let s=e.indexOf("=");return-1===s&&(s=t),[s,s===t?0:4-s%4]}static _byteLength(e,t){return 3*(e+t)/4-t}static _tripletToBase64(e){return r._lookup[e>>18&63]+r._lookup[e>>12&63]+r._lookup[e>>6&63]+r._lookup[63&e]}static _encodeChunk(e,t,s){const n=[];for(let i=t;i<s;i+=3){const t=(e[i]<<16&16711680)+(e[i+1]<<8&65280)+(255&e[i+2]);n.push(r._tripletToBase64(t))}return n.join("")}}var n,i,o;r._lookup="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",r._revLookup=[],function(e){e[e.UINT8_ARRAY=0]="UINT8_ARRAY"}(n||(n={}));class a{static stringify(e){return JSON.stringify(e,a._jsonifyType)}static parse(e){return JSON.parse(e,a._parseType)}static _parseType(e,t){if(t&&t.hasOwnProperty&&t.hasOwnProperty(a.TYPE_SYMBOL)&&t.hasOwnProperty(a.VALUE_SYMBOL))switch(t[a.TYPE_SYMBOL]){case n.UINT8_ARRAY:return r.decode(t[a.VALUE_SYMBOL])}return t}static _jsonifyType(e,t){return t instanceof Uint8Array?a._typedObject(n.UINT8_ARRAY,r.encode(t)):t}static _typedObject(e,t){const s={};return s[a.TYPE_SYMBOL]=e,s[a.VALUE_SYMBOL]=t,s}}a.TYPE_SYMBOL="__",a.VALUE_SYMBOL="v";class c{constructor(e=!0){this._store=e?window.sessionStorage:null,this._validIds=new Map,e&&this._restoreIds()}static _decodeIds(e){const t=a.parse(e),s=new Map;for(const e of Object.keys(t)){const r=parseInt(e,10);s.set(isNaN(r)?e:r,t[e])}return s}has(e){return this._validIds.has(e)}getCommand(e){const t=this._validIds.get(e);return t?t[0]:null}getState(e){const t=this._validIds.get(e);return t?t[1]:null}add(e,t,s=null){this._validIds.set(e,[t,s]),this._storeIds()}remove(e){this._validIds.delete(e),this._storeIds()}clear(){this._validIds.clear(),this._store&&this._store.removeItem(c.KEY)}_encodeIds(){const e=Object.create(null);for(const[t,s]of this._validIds)e[t]=s;return a.stringify(e)}_restoreIds(){const e=this._store.getItem(c.KEY);e&&(this._validIds=c._decodeIds(e))}_storeIds(){this._store&&this._store.setItem(c.KEY,this._encodeIds())}}c.KEY="rpcRequests";class d{static receiveRedirectCommand(e){if(!document.referrer)return null;const t=new URLSearchParams(e.search),r=new URL(document.referrer);if(!t.has("command"))return null;if(!t.has("id"))return null;if(!t.has("returnURL"))return null;const n=t.get("returnURL")===s&&window.opener;if(!n){if(new URL(t.get("returnURL")).origin!==r.origin)return null}let i=[];if(t.has("args"))try{i=a.parse(t.get("args"))}catch(e){}return i=Array.isArray(i)?i:[],{origin:r.origin,data:{id:parseInt(t.get("id"),10),command:t.get("command"),args:i},returnURL:t.get("returnURL"),source:n?window.opener:null}}static receiveRedirectResponse(e){if(!document.referrer)return null;const s=new URLSearchParams(e.search),r=new URL(document.referrer);if(!s.has("status"))return null;if(!s.has("id"))return null;if(!s.has("result"))return null;const n=a.parse(s.get("result")),i=s.get("status")===t.OK?t.OK:t.ERROR;return{origin:r.origin,data:{id:parseInt(s.get("id"),10),status:i,result:n}}}static prepareRedirectReply(e,t,s){const r=new URLSearchParams;return r.set("status",t),r.set("result",a.stringify(s)),r.set("id",e.id.toString()),`${e.returnURL}${new URL(e.returnURL).search.length>0?"&":"?"}${r.toString()}`}static prepareRedirectInvocation(e,t,s,r,n){const i=new URLSearchParams;return i.set("id",t.toString()),i.set("returnURL",s),i.set("command",r),Array.isArray(n)&&i.set("args",a.stringify(n)),`${e}?${i.toString()}`}}class l{constructor(e,t=!1){this._allowedOrigin=e,this._waitingRequests=new c(t),this._responseHandlers=new Map}onResponse(e,t,s){this._responseHandlers.set(e,{resolve:t,reject:s})}_receive(e){if(!e.data||!e.data.status||!e.data.id||"*"!==this._allowedOrigin&&e.origin!==this._allowedOrigin)return;const s=e.data,r=this._getCallback(s.id),n=this._waitingRequests.getState(s.id);if(r){if(console.debug("RpcClient RECEIVE",s),s.status===t.OK)r.resolve(s.result,s.id,n);else if(s.status===t.ERROR){const e=new Error(s.result.message);s.result.stack&&(e.stack=s.result.stack),s.result.name&&(e.name=s.result.name),r.reject(e,s.id,n)}}else console.warn("Unknown RPC response:",s)}_getCallback(e){if(this._responseHandlers.has(e))return this._responseHandlers.get(e);{const t=this._waitingRequests.getCommand(e);if(t)return this._responseHandlers.get(t)}}}class u extends l{constructor(e,t){super(t),this._target=e,this._connected=!1,this._receiveListener=this._receive.bind(this)}async init(){await this._connect(),window.addEventListener("message",this._receiveListener)}async call(t,...s){if(!this._connected)throw new Error("Client is not connected, call init first");return new Promise((r,n)=>{const i={command:t,args:s,id:e.generateRandomId()};this._responseHandlers.set(i.id,{resolve:r,reject:n}),this._waitingRequests.add(i.id,t);const o=()=>{this._target.closed&&n(new Error("Window was closed")),setTimeout(o,500)};setTimeout(o,500),console.debug("RpcClient REQUEST",t,s),this._target.postMessage(i,this._allowedOrigin)})}close(){window.removeEventListener("message",this._receiveListener),this._connected=!1}_connect(){return new Promise((e,s)=>{const r=s=>{const{source:n,origin:i,data:o}=s;if(n===this._target&&o.status===t.OK&&"pong"===o.result&&1===o.id&&("*"===this._allowedOrigin||i===this._allowedOrigin)){if(o.result.stack){const e=new Error(o.result.message);e.stack=o.result.stack,o.result.name&&(e.name=o.result.name),console.error(e)}window.removeEventListener("message",r),this._connected=!0,console.log("RpcClient: Connection established"),window.addEventListener("message",this._receiveListener),e(!0)}};window.addEventListener("message",r);let n=0;const i=setTimeout(()=>{window.removeEventListener("message",r),clearTimeout(n),s(new Error("Connection timeout"))},1e4),o=()=>{if(this._connected)clearTimeout(i);else{try{this._target.postMessage({command:"ping",id:1},this._allowedOrigin)}catch(e){console.error(`postMessage failed: ${e}`)}n=setTimeout(o,1e3)}};n=setTimeout(o,100)})}}class h extends u{constructor(e,t,s){super(e,t),this._requestId=s}async init(){window.addEventListener("message",this._receiveListener)}async listenFor(e){return new Promise((t,s)=>{this._responseHandlers.set(this._requestId,{resolve:t,reject:s}),this._waitingRequests.add(this._requestId,e);const r=()=>{this._target.closed&&s(new Error("Window was closed")),setTimeout(r,500)};setTimeout(r,500)})}}class _ extends l{constructor(e,t){super(t,!0),this._target=e}async init(){const e=d.receiveRedirectResponse(window.location);e?this._receive(e):d.receiveRedirectCommand(window.location)||this._rejectOnBack()}close(){}call(e,t,...s){this.callAndSaveLocalState(e,null,t,...s)}callAndSaveLocalState(t,s,r,...n){const i=e.generateRandomId(),o=d.prepareRedirectInvocation(this._target,i,t,r,n);this._waitingRequests.add(i,r,s),history.replaceState({rpcRequestId:i},document.title),console.debug("RpcClient REQUEST",r,n),window.location.href=o}_rejectOnBack(){if(history.state&&history.state.rpcRequestId){const e=history.state.rpcRequestId,t=this._getCallback(e),s=this._waitingRequests.getState(e);if(t){console.debug("RpcClient BACK");const r=new Error("Request aborted");t.reject(r,e,s)}}}}class p{static getAllowedOrigin(e){return new URL(e).origin}constructor(e){this._type=e}async request(e,t,s){throw new Error("Not implemented")}get type(){return this._type}}!function(e){e[e.REDIRECT=0]="REDIRECT",e[e.POPUP=1]="POPUP",e[e.IFRAME=2]="IFRAME"}(i||(i={}));class g extends p{static withLocalState(e){return new g(void 0,e)}constructor(e,t){super(i.REDIRECT);const s=window.location;if(this._returnUrl=e||`${s.origin}${s.pathname}`,this._localState=t||{},void 0!==this._localState.__command)throw new Error("Invalid localState: Property '__command' is reserved")}async request(e,t,s){const r=p.getAllowedOrigin(e),n=new _(e,r);await n.init();const i=Object.assign({},this._localState,{__command:t});console.log("state",i),n.callAndSaveLocalState(this._returnUrl,JSON.stringify(i),t,...s)}}class w extends p{constructor(e=w.DEFAULT_OPTIONS){super(i.POPUP),this._options=e}async request(t,s,r){const n=p.getAllowedOrigin(t),i=e.generateRandomId(),o=d.prepareRedirectInvocation(t,i,"<postMessage>",s,r),a=this.createPopup(o),c=new h(a,n,i);await c.init();try{const e=await c.listenFor(s);return c.close(),a.close(),e}catch(e){throw c.close(),a.close(),e}}createPopup(e){const t=window.open(e,"NimiqAccounts",this._options);if(!t)throw new Error("Failed to open popup");return t}}w.DEFAULT_OPTIONS="";class m extends p{constructor(){super(i.IFRAME),this._iframe=null,this._client=null}async request(e,t,s){if(this._iframe&&this._iframe.src!==`${e}${m.IFRAME_PATH_SUFFIX}`)throw new Error("Accounts Manager iframe is already opened with another endpoint");const r=p.getAllowedOrigin(e);if(this._iframe||(this._iframe=await this.createIFrame(e)),!this._iframe.contentWindow)throw new Error(`IFrame contentWindow is ${typeof this._iframe.contentWindow}`);return this._client||(this._client=new u(this._iframe.contentWindow,r),await this._client.init()),await this._client.call(t,...s)}async createIFrame(e){return new Promise((t,s)=>{const r=document.createElement("iframe");r.name="NimiqAccountsIFrame",r.style.display="none",document.body.appendChild(r),r.src=`${e}${m.IFRAME_PATH_SUFFIX}`,r.onload=(()=>t(r)),r.onerror=s})}}m.IFRAME_PATH_SUFFIX="/iframe.html",function(e){e.LIST="list",e.MIGRATE="migrate",e.CHECKOUT="checkout",e.SIGN_MESSAGE="sign-message",e.SIGN_TRANSACTION="sign-transaction",e.ONBOARD="onboard",e.SIGNUP="signup",e.LOGIN="login",e.EXPORT="export",e.CHANGE_PASSPHRASE="change-passphrase",e.LOGOUT="logout",e.ADD_ACCOUNT="add-account",e.RENAME="rename",e.CHOOSE_ADDRESS="choose-address"}(o||(o={}));class R{constructor(e=R.DEFAULT_ENDPOINT,t){this._endpoint=e,this._defaultBehavior=t||new w(`left=${window.innerWidth/2-500},top=50,width=1000,height=900,location=yes,dependent=yes`),this._iframeBehavior=new m,this._redirectClient=new _("",p.getAllowedOrigin(this._endpoint))}checkRedirectResponse(){return this._redirectClient.init()}on(e,t,s){this._redirectClient.onResponse(e,(e,s,r)=>t(e,JSON.parse(r)),(e,t,r)=>s&&s(e,JSON.parse(r)))}onboard(e,t=this._defaultBehavior){return this._request(t,o.ONBOARD,[e])}signup(e,t=this._defaultBehavior){return this._request(t,o.SIGNUP,[e])}login(e,t=this._defaultBehavior){return this._request(t,o.LOGIN,[e])}chooseAddress(e,t=this._defaultBehavior){return this._request(t,o.CHOOSE_ADDRESS,[e])}signTransaction(e,t=this._defaultBehavior){return this._request(t,o.SIGN_TRANSACTION,[e])}checkout(e,t=this._defaultBehavior){return this._request(t,o.CHECKOUT,[e])}logout(e,t=this._defaultBehavior){return this._request(t,o.LOGOUT,[e])}export(e,t=this._defaultBehavior){return this._request(t,o.EXPORT,[e])}changePassphrase(e,t=this._defaultBehavior){return this._request(t,o.CHANGE_PASSPHRASE,[e])}addAccount(e,t=this._defaultBehavior){return this._request(t,o.ADD_ACCOUNT,[e])}rename(e,t=this._defaultBehavior){return this._request(t,o.RENAME,[e])}signMessage(e,t=this._defaultBehavior){return this._request(t,o.SIGN_MESSAGE,[e])}migrate(e=this._defaultBehavior){return this._request(e,o.MIGRATE,[{}])}list(e=this._iframeBehavior){return this._request(e,o.LIST,[])}_request(e,t,s){return e.request(this._endpoint,t,s)}}return R.RequestType=o,R.RedirectRequestBehavior=g,R.DEFAULT_ENDPOINT="https://safe-next.nimiq.com"===window.location.origin?"https://accounts.nimiq.com":"https://safe-next.nimiq-testnet.com"===window.location.origin?"https://accounts.nimiq-testnet.com":"http://localhost:8080",R});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.AccountsClient=t()}(this,function(){"use strict";class e{static generateRandomId(){const e=new Uint32Array(1);return crypto.getRandomValues(e),e[0]}}var t;!function(e){e.OK="ok",e.ERROR="error"}(t||(t={}));const s="<postMessage>";class r{static byteLength(e){const[t,s]=r._getLengths(e);return r._byteLength(t,s)}static decode(e){r._initRevLookup();const[t,s]=r._getLengths(e),n=new Uint8Array(r._byteLength(t,s));let i=0;const o=s>0?t-4:t;let a=0;for(;a<o;a+=4){const t=r._revLookup[e.charCodeAt(a)]<<18|r._revLookup[e.charCodeAt(a+1)]<<12|r._revLookup[e.charCodeAt(a+2)]<<6|r._revLookup[e.charCodeAt(a+3)];n[i++]=t>>16&255,n[i++]=t>>8&255,n[i++]=255&t}if(2===s){const t=r._revLookup[e.charCodeAt(a)]<<2|r._revLookup[e.charCodeAt(a+1)]>>4;n[i++]=255&t}if(1===s){const t=r._revLookup[e.charCodeAt(a)]<<10|r._revLookup[e.charCodeAt(a+1)]<<4|r._revLookup[e.charCodeAt(a+2)]>>2;n[i++]=t>>8&255,n[i]=255&t}return n}static encode(e){const t=e.length,s=t%3,n=[];for(let i=0,o=t-s;i<o;i+=16383)n.push(r._encodeChunk(e,i,i+16383>o?o:i+16383));if(1===s){const s=e[t-1];n.push(r._lookup[s>>2]+r._lookup[s<<4&63]+"==")}else if(2===s){const s=(e[t-2]<<8)+e[t-1];n.push(r._lookup[s>>10]+r._lookup[s>>4&63]+r._lookup[s<<2&63]+"=")}return n.join("")}static encodeUrl(e){return r.encode(e).replace(/\//g,"_").replace(/\+/g,"-").replace(/=/g,".")}static decodeUrl(e){return r.decode(e.replace(/_/g,"/").replace(/-/g,"+").replace(/\./g,"="))}static _initRevLookup(){if(0===r._revLookup.length){r._revLookup=[];for(let e=0,t=r._lookup.length;e<t;e++)r._revLookup[r._lookup.charCodeAt(e)]=e;r._revLookup["-".charCodeAt(0)]=62,r._revLookup["_".charCodeAt(0)]=63}}static _getLengths(e){const t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");let s=e.indexOf("=");return-1===s&&(s=t),[s,s===t?0:4-s%4]}static _byteLength(e,t){return 3*(e+t)/4-t}static _tripletToBase64(e){return r._lookup[e>>18&63]+r._lookup[e>>12&63]+r._lookup[e>>6&63]+r._lookup[63&e]}static _encodeChunk(e,t,s){const n=[];for(let i=t;i<s;i+=3){const t=(e[i]<<16&16711680)+(e[i+1]<<8&65280)+(255&e[i+2]);n.push(r._tripletToBase64(t))}return n.join("")}}var n,i,o;r._lookup="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",r._revLookup=[],function(e){e[e.UINT8_ARRAY=0]="UINT8_ARRAY"}(n||(n={}));class a{static stringify(e){return JSON.stringify(e,a._jsonifyType)}static parse(e){return JSON.parse(e,a._parseType)}static _parseType(e,t){if(t&&t.hasOwnProperty&&t.hasOwnProperty(a.TYPE_SYMBOL)&&t.hasOwnProperty(a.VALUE_SYMBOL))switch(t[a.TYPE_SYMBOL]){case n.UINT8_ARRAY:return r.decode(t[a.VALUE_SYMBOL])}return t}static _jsonifyType(e,t){return t instanceof Uint8Array?a._typedObject(n.UINT8_ARRAY,r.encode(t)):t}static _typedObject(e,t){const s={};return s[a.TYPE_SYMBOL]=e,s[a.VALUE_SYMBOL]=t,s}}a.TYPE_SYMBOL="__",a.VALUE_SYMBOL="v";class c{constructor(e=!0){this._store=e?window.sessionStorage:null,this._validIds=new Map,e&&this._restoreIds()}static _decodeIds(e){const t=a.parse(e),s=new Map;for(const e of Object.keys(t)){const r=parseInt(e,10);s.set(isNaN(r)?e:r,t[e])}return s}has(e){return this._validIds.has(e)}getCommand(e){const t=this._validIds.get(e);return t?t[0]:null}getState(e){const t=this._validIds.get(e);return t?t[1]:null}add(e,t,s=null){this._validIds.set(e,[t,s]),this._storeIds()}remove(e){this._validIds.delete(e),this._storeIds()}clear(){this._validIds.clear(),this._store&&this._store.removeItem(c.KEY)}_encodeIds(){const e=Object.create(null);for(const[t,s]of this._validIds)e[t]=s;return a.stringify(e)}_restoreIds(){const e=this._store.getItem(c.KEY);e&&(this._validIds=c._decodeIds(e))}_storeIds(){this._store&&this._store.setItem(c.KEY,this._encodeIds())}}c.KEY="rpcRequests";class l{static receiveRedirectCommand(e){if(!document.referrer)return null;const t=new URLSearchParams(e.search),r=new URL(document.referrer);if(!t.has("command"))return null;if(!t.has("id"))return null;if(!t.has("returnURL"))return null;const n=t.get("returnURL")===s&&(window.opener||window.parent);if(!n){if(new URL(t.get("returnURL")).origin!==r.origin)return null}let i=[];if(t.has("args"))try{i=a.parse(t.get("args"))}catch(e){}return i=Array.isArray(i)?i:[],{origin:r.origin,data:{id:parseInt(t.get("id"),10),command:t.get("command"),args:i},returnURL:t.get("returnURL"),source:n?window.opener||window.parent:null}}static receiveRedirectResponse(e){if(!document.referrer)return null;const s=new URLSearchParams(e.search),r=new URL(document.referrer);if(!s.has("status"))return null;if(!s.has("id"))return null;if(!s.has("result"))return null;const n=a.parse(s.get("result")),i=s.get("status")===t.OK?t.OK:t.ERROR;return{origin:r.origin,data:{id:parseInt(s.get("id"),10),status:i,result:n}}}static prepareRedirectReply(e,t,s){const r=new URL(e.returnURL),n=r.searchParams;return n.set("status",t),n.set("result",a.stringify(s)),n.set("id",e.id.toString()),r.href}static prepareRedirectInvocation(e,t,s,r,n){const i=new URL(e),o=i.searchParams;return o.set("id",t.toString()),o.set("returnURL",s),o.set("command",r),Array.isArray(n)&&o.set("args",a.stringify(n)),i.href}}class d{constructor(e,t=!1){this._allowedOrigin=e,this._waitingRequests=new c(t),this._responseHandlers=new Map,this._preserveRequests=!1}onResponse(e,t,s){this._responseHandlers.set(e,{resolve:t,reject:s})}_receive(e){if(!e.data||!e.data.status||!e.data.id||"*"!==this._allowedOrigin&&e.origin!==this._allowedOrigin)return;const s=e.data,r=this._getCallback(s.id),n=this._waitingRequests.getState(s.id);if(r){if(this._preserveRequests||(this._waitingRequests.remove(s.id),this._responseHandlers.delete(s.id)),console.debug("RpcClient RECEIVE",s),s.status===t.OK)r.resolve(s.result,s.id,n);else if(s.status===t.ERROR){const e=new Error(s.result.message);s.result.stack&&(e.stack=s.result.stack),s.result.name&&(e.name=s.result.name),r.reject(e,s.id,n)}}else console.warn("Unknown RPC response:",s)}_getCallback(e){if(this._responseHandlers.has(e))return this._responseHandlers.get(e);{const t=this._waitingRequests.getCommand(e);if(t)return this._responseHandlers.get(t)}}}class u extends d{constructor(e,t){super(t),this._serverCloseCheckInterval=-1,this._target=e,this._connectionState=0,this._receiveListener=this._receive.bind(this)}async init(){2!==this._connectionState&&(await this._connect(),window.addEventListener("message",this._receiveListener),-1===this._serverCloseCheckInterval&&(this._serverCloseCheckInterval=window.setInterval(()=>this._checkIfServerClosed(),300)))}async call(t,...s){return this._call({command:t,args:s,id:e.generateRandomId()})}async callAndPersist(t,...s){return this._call({command:t,args:s,id:e.generateRandomId(),persistInUrl:!0})}close(){this._connectionState=0,window.removeEventListener("message",this._receiveListener),window.clearInterval(this._serverCloseCheckInterval),this._serverCloseCheckInterval=-1;for(const[e,{reject:t}]of this._responseHandlers){const s=this._waitingRequests.getState(e);t("Connection was closed","number"==typeof e?e:void 0,s)}this._waitingRequests.clear(),this._responseHandlers.clear(),this._target&&this._target.closed&&(this._target=null)}_receive(e){e.source===this._target&&super._receive(e)}async _call(e){if(!this._target||this._target.closed)throw new Error("Connection was closed.");if(2!==this._connectionState)throw new Error("Client is not connected, call init first");return new Promise((t,s)=>{this._responseHandlers.set(e.id,{resolve:t,reject:s}),this._waitingRequests.add(e.id,e.command),console.debug("RpcClient REQUEST",e.command,e.args),this._target.postMessage(e,this._allowedOrigin)})}_connect(){if(2!==this._connectionState)return this._connectionState=1,new Promise((e,s)=>{const r=s=>{const{source:n,origin:i,data:o}=s;if(n===this._target&&o.status===t.OK&&"pong"===o.result&&1===o.id&&("*"===this._allowedOrigin||i===this._allowedOrigin)){if(o.result.stack){const e=new Error(o.result.message);e.stack=o.result.stack,o.result.name&&(e.name=o.result.name),console.error(e)}window.removeEventListener("message",r),this._connectionState=2,console.log("RpcClient: Connection established"),e(!0)}};window.addEventListener("message",r);const n=()=>{if(2!==this._connectionState){if(0===this._connectionState||this._checkIfServerClosed())return window.removeEventListener("message",r),void s(new Error("Connection was closed"));try{this._target.postMessage({command:"ping",id:1},this._allowedOrigin)}catch(e){console.error(`postMessage failed: ${e}`)}window.setTimeout(n,100)}};window.setTimeout(n,100)})}_checkIfServerClosed(){return!(this._target&&!this._target.closed)&&(this.close(),!0)}}class h extends d{constructor(e,t,s=!0){super(t,!0),this._target=e,this._preserveRequests=s}async init(){const e=l.receiveRedirectResponse(window.location);e?this._receive(e):l.receiveRedirectCommand(window.location)||this._rejectOnBack()}close(){}call(e,t,...s){this.callAndSaveLocalState(e,null,t,...s)}callAndSaveLocalState(t,s,r,...n){const i=e.generateRandomId(),o=l.prepareRedirectInvocation(this._target,i,t,r,n);this._waitingRequests.add(i,r,s),history.replaceState({rpcRequestId:i},document.title),console.debug("RpcClient REQUEST",r,n),window.location.href=o}_rejectOnBack(){if(history.state&&history.state.rpcRequestId){const e=history.state.rpcRequestId,t=this._getCallback(e),s=this._waitingRequests.getState(e);if(t){this._preserveRequests||(this._waitingRequests.remove(e),this._responseHandlers.delete(e)),console.debug("RpcClient BACK");const r=new Error("Request aborted");t.reject(r,e,s)}}}}class _{static getAllowedOrigin(e){return new URL(e).origin}constructor(e){this._type=e}async request(e,t,s){throw new Error("Not implemented")}get type(){return this._type}}!function(e){e[e.REDIRECT=0]="REDIRECT",e[e.POPUP=1]="POPUP",e[e.IFRAME=2]="IFRAME"}(i||(i={}));class p extends _{static withLocalState(e){return new p(void 0,e)}constructor(e,t){super(i.REDIRECT);const s=window.location;if(this._returnUrl=e||`${s.origin}${s.pathname}`,this._localState=t||{},void 0!==this._localState.__command)throw new Error("Invalid localState: Property '__command' is reserved")}async request(e,t,s){const r=_.getAllowedOrigin(e),n=new h(e,r);await n.init();const i=Object.assign({},this._localState,{__command:t});n.callAndSaveLocalState(this._returnUrl,i,t,...s)}}class g extends _{constructor(e=g.DEFAULT_OPTIONS){super(i.POPUP),this._options=e}async request(e,t,s){const r=_.getAllowedOrigin(e),n=this.createPopup(e),i=new u(n,r);await i.init();try{return await i.callAndPersist(t,...s)}catch(e){throw e}finally{i.close(),n.close()}}createPopup(e){const t=window.open(e,"NimiqAccounts",this._options);if(!t)throw new Error("Failed to open popup");return t}}g.DEFAULT_OPTIONS="";class w extends _{constructor(){super(i.IFRAME),this._iframe=null,this._client=null}async request(e,t,s){if(this._iframe&&this._iframe.src!==`${e}${w.IFRAME_PATH_SUFFIX}`)throw new Error("Accounts Manager iframe is already opened with another endpoint");const r=_.getAllowedOrigin(e);if(this._iframe||(this._iframe=await this.createIFrame(e)),!this._iframe.contentWindow)throw new Error(`IFrame contentWindow is ${typeof this._iframe.contentWindow}`);return this._client||(this._client=new u(this._iframe.contentWindow,r),await this._client.init()),await this._client.call(t,...s)}async createIFrame(e){return new Promise((t,s)=>{const r=document.createElement("iframe");r.name="NimiqAccountsIFrame",r.style.display="none",document.body.appendChild(r),r.src=`${e}${w.IFRAME_PATH_SUFFIX}`,r.onload=(()=>t(r)),r.onerror=s})}}w.IFRAME_PATH_SUFFIX="/iframe.html",function(e){e.LIST="list",e.MIGRATE="migrate",e.CHECKOUT="checkout",e.SIGN_MESSAGE="sign-message",e.SIGN_TRANSACTION="sign-transaction",e.ONBOARD="onboard",e.SIGNUP="signup",e.LOGIN="login",e.EXPORT="export",e.CHANGE_PASSWORD="change-password",e.LOGOUT="logout",e.ADD_ADDRESS="add-address",e.RENAME="rename",e.CHOOSE_ADDRESS="choose-address"}(o||(o={}));class m{constructor(e=m.DEFAULT_ENDPOINT,t){this._endpoint=e,this._defaultBehavior=t||new g(`left=${window.innerWidth/2-400},top=75,width=800,height=850,location=yes,dependent=yes`),this._iframeBehavior=new w,this._redirectClient=new h("",_.getAllowedOrigin(this._endpoint))}static get DEFAULT_ENDPOINT(){const e=location.origin.split(".");switch(e.shift(),e.join(".")){case"nimiq.com":return"https://accounts.nimiq.com";case"nimiq-testnet.com":return"https://accounts.nimiq-testnet.com";default:return"http://localhost:8080"}}checkRedirectResponse(){return this._redirectClient.init()}on(e,t,s){this._redirectClient.onResponse(e,(e,s,r)=>t(e,r),(e,t,r)=>s&&s(e,r))}onboard(e,t=this._defaultBehavior){return this._request(t,o.ONBOARD,[e])}signup(e,t=this._defaultBehavior){return this._request(t,o.SIGNUP,[e])}login(e,t=this._defaultBehavior){return this._request(t,o.LOGIN,[e])}chooseAddress(e,t=this._defaultBehavior){return this._request(t,o.CHOOSE_ADDRESS,[e])}signTransaction(e,t=this._defaultBehavior){return this._request(t,o.SIGN_TRANSACTION,[e])}checkout(e,t=this._defaultBehavior){return this._request(t,o.CHECKOUT,[e])}logout(e,t=this._defaultBehavior){return this._request(t,o.LOGOUT,[e])}export(e,t=this._defaultBehavior){return this._request(t,o.EXPORT,[e])}changePassword(e,t=this._defaultBehavior){return this._request(t,o.CHANGE_PASSWORD,[e])}addAddress(e,t=this._defaultBehavior){return this._request(t,o.ADD_ADDRESS,[e])}rename(e,t=this._defaultBehavior){return this._request(t,o.RENAME,[e])}signMessage(e,t=this._defaultBehavior){return this._request(t,o.SIGN_MESSAGE,[e])}migrate(e=this._defaultBehavior){return this._request(e,o.MIGRATE,[{appName:"Accounts Client"}])}list(e=this._iframeBehavior){return this._request(e,o.LIST,[])}_request(e,t,s){return e.request(this._endpoint,t,s)}}return m.RequestType=o,m.RedirectRequestBehavior=p,m});
{
"name": "@nimiq/accounts-client",
"version": "0.1.3",
"version": "0.2.0",
"main": "dist/AccountsClient.umd.js",

@@ -11,3 +11,3 @@ "module": "dist/AccountsClient.es.js",

"dependencies": {
"@nimiq/rpc": "^0.1.0-beta.5"
"@nimiq/rpc": "^0.1.4"
},

@@ -19,3 +19,3 @@ "devDependencies": {

"tslint": "^5.11.0",
"typescript": "^3.0.3"
"typescript": "^3.3.3333"
},

@@ -22,0 +22,0 @@ "files": [

@@ -9,20 +9,26 @@ # Nimiq Accounts Manager <!-- omit in toc -->

- [The Accounts Client library](#the-accounts-client-library)
- [Installation](#installation)
- [Initialization](#initialization)
- [Usage](#usage)
- [Using top-level redirects](#using-top-level-redirects)
- [API Methods](#api-methods)
- [Checkout](#checkout)
- [Choose Address](#choose-address)
- [Sign transaction](#sign-transaction)
- [Signup](#signup)
- [Login](#login)
- [Logout](#logout)
- [Export](#export)
- [Listening for redirect responses](#listening-for-redirect-responses)
- [Installation](#installation)
- [Initialization](#initialization)
- [Usage](#usage)
- [Using top-level redirects](#using-top-level-redirects)
- [API Methods](#api-methods)
- [Checkout](#checkout)
- [Choose Address](#choose-address)
- [Sign Transaction](#sign-transaction)
- [Signup](#signup)
- [Login](#login)
- [Onboard](#onboard)
- [Logout](#logout)
- [Export](#export)
- [Change Password](#change-password)
- [Add Address](#add-address)
- [Rename](#rename)
- [Sign Message](#sign-message)
- [Listening for redirect responses](#listening-for-redirect-responses)
- [Running your own Accounts Manager](#running-your-own-accounts-manager)
- [Contribute](#contribute)
- [Setup](#setup)
- [Run](#run)
- [Build](#build)
- [Setup](#setup)
- [Run](#run)
- [Build](#build)
- [Configuration](#configuration)

@@ -37,5 +43,5 @@ ## The Accounts Client library

<!-- From CDN -->
<script src="https://unpkg.com/@nimiq/accounts-client@v0.1/dist/standalone/AccountsClient.standalone.umd.js"></script>
<script src="https://unpkg.com/@nimiq/accounts-client@v0.2/dist/standalone/AccountsClient.standalone.umd.js"></script>
<!-- or -->
<script src="https://cdn.jsdelivr.net/npm/@nimiq/accounts-client@v0.1/dist/standalone/AccountsClient.standalone.umd.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@nimiq/accounts-client@v0.2/dist/standalone/AccountsClient.standalone.umd.js"></script>
```

@@ -93,2 +99,5 @@

> **Note:** To use redirects instead of popups, your app must run under a
> HTTPS domain!
If you prefer top-level redirects instead of popups, you can pass an

@@ -98,2 +107,5 @@ instance of `RedirectRequestBehavior` as a second parameter to either the

> **Note:** The way to configure top-level redirects will change in an upcoming
> version of the Accounts Client!
```javascript

@@ -133,19 +145,22 @@ const redirectBehavior = new AccountsClient.RedirectRequestBehavior();

- [Choose Address](#choose-address)
- [Sign transaction](#sign-transaction)
- [Sign Transaction](#sign-transaction)
- [Signup](#signup)
- [Login](#login)
- [Onboard](#onboard)
- [Logout](#logout)
- [Export](#export)
- [Change Password](#change-password)
- [Add Address](#add-address)
- [Rename](#rename)
- [Sign Message](#sign-message)
[//] TODO: Add methods 'onboard', 'changePassphrase', 'addAccount', 'rename', 'signMessage'
> **Note:**
>
> All API methods run asynchronously and thus return promises. Please keep in
> mind that promises can also be rejected for various reasons, e.g. if the user
> mind that promises can also be rejected for various reasons, e.g. when the user
> cancels the request by closing the popup window or clicking on a cancel
> button.
>
> An error can also occur when the request contains invalid parameters. The
> `Error` object will be passed on to the `reject` handler.
> An error can also occur when the request contains invalid parameters. The request
> promise will be rejected with an `Error` object.

@@ -193,31 +208,45 @@ #### Checkout

//flags: Nimiq.Transaction.Flag.CONTRACT_CREATION,
// [optional] The duration (in number of blocks) that the signed transaction
// should be valid for. The maximum is 120.
// Default: 120
//validityDuration?: number;
};
// All client requests are async and return a promise
const checkoutResult = await accountsClient.checkout(requestOptions);
const signedTransaction = await accountsClient.checkout(requestOptions);
```
The `checkout()` method returns a promise which resolves to a
`SignTransactionResult`:
`SignedTransaction`:
```javascript
interface SignTransactionResult {
serializedTx: Uint8Array; // The signed, serialized transaction
sender: string; // Human-readable address of sender
senderType: Nimiq.Account.Type; // 0, 1, 2 - see recipientType above
senderPubKey: Uint8Array; // Serialized public key of the sender
recipient: string; // Human-readable address of recipient
recipientType: Nimiq.Account.Type; // 0, 1, 2 - see above
value: number;
fee: number;
validityStartHeight: number; // Automatically determined validity
// start height of the transaction
signature: Uint8Array; // Serialized signature of the sender
extraData: Uint8Array;
flags: number;
networkId: number;
hash: string; // Base64 transaction hash
interface SignedTransaction {
serializedTx: string; // HEX signed and serialized transaction
hash: string; // HEX transaction hash
raw: {
signerPublicKey: Uint8Array; // Serialized public key of the signer
signature: Uint8Array; // Serialized signature of the signer
sender: string; // Human-readable address of sender
senderType: Nimiq.Account.Type; // 0, 1, 2 - see recipientType above
recipient: string; // Human-readable address of recipient
recipientType: Nimiq.Account.Type; // 0, 1, 2 - see above
value: number;
fee: number;
validityStartHeight: number; // Automatically determined validity
// start height of the transaction
extraData: Uint8Array;
flags: number;
networkId: number;
}
}
```
The `serializedTx` can be handed to a Nimiq JSON-RPC's `sendRawTransaction` method.
The `raw` object can be handed to the NanoApi's `relayTransaction` method.
#### Choose Address

@@ -227,8 +256,8 @@

their addresses to provide to your website. This can be used for example to find
out, which address your app should send funds to.
out which address your app should send funds to.
**Note:** This method should not yet be used as a login or authentication mechanism,
**Note:** This method should not be used as a login or authentication mechanism,
as it does not provide any security that the user actually owns the provided address!
The method takes a simple request object as its only argument, which must only contain
The method takes a basic request object as its only argument, which must only contain
the `appName` property:

@@ -243,19 +272,19 @@

// All client requests are async and return a promise
const providedAddress = await accountsClient.chooseAddress(requestOptions);
const address = await accountsClient.chooseAddress(requestOptions);
```
The request's result contains a userfriendly address string as `address` and a `label`:
The request's result contains an address string as `address` and a `label`:
```javascript
providedAddress = {
address: 'NQ07 0000 0000 0000 0000 0000 0000 0000 0000',
label: 'Burner Address',
interface Address {
address: string; // Human-readable address
label: string; // The address's label (name)
}
```
#### Sign transaction
#### Sign Transaction
The `signTransaction()` method is similar to checkout, but provides a different
UI to the user. The main difference to `checkout()` is that it requires the
request to already include the sender's account (wallet) ID and address as `walletId` and
request to already include the sender's account ID and address as `accountId` and
`sender` respectively, as well as the transaction's `validityStartHeight`. The

@@ -273,3 +302,3 @@ created transaction will only be returned to the caller, not sent to the network

// Sender information
walletId: 'xxxxxxxx',
accountId: 'xxxxxxxx',
sender: 'NQxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx',

@@ -296,6 +325,6 @@

// All client requests are async and return a promise
const signTxResult = await accountsClient.signTransaction(requestOptions);
const signedTransaction = await accountsClient.signTransaction(requestOptions);
```
The `signTransaction()` method returns a `SignTransactionResult` as well. See
The `signTransaction()` method returns a `SignedTransaction`. See
[Checkout](#checkout) for details.

@@ -315,11 +344,11 @@

// All client requests are async and return a promise
const newAccount = await accountsClient.signup(requestOptions);
const account = await accountsClient.signup(requestOptions);
```
The `signup()` method returns a promise which resolves to a `SignupResult`:
The `signup()` method returns a promise which resolves to an `Account`:
```javascript
interface SignupResult {
walletId: string; // Automatically generated account (wallet) ID
label: string; // The label/name given to the account by the user
interface Account {
accountId: string; // Automatically generated account ID
label: string; // The label (name) generated for the account

@@ -329,5 +358,8 @@ type: WalletType; // 1 for in-browser multi-address accounts,

accounts: Array<{ // During signup, only one address is added to the account
fileExported: boolean; // These two flags signal if the user already
wordsExported: boolean; // has the Login File or the recovery words
addresses: Array<{ // During signup, only one address is added to the account
address: string; // Human-readable address
label: string; // The label/name given to the address by the user
label: string; // The label (name) of the address
}>;

@@ -341,3 +373,3 @@ }

**Accounts Manager** by importing their *Login File*, *Recovery Words* or
*Account Access File*. After an account has been imported, the
old *Account Access File*. After an account has been imported, the
**Accounts Manager** automatically detects active addresses following the

@@ -354,26 +386,26 @@ [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#account-discovery)

// All client requests are async and return a promise
const newAccount = await accountsClient.login(requestOptions);
const account = await accountsClient.login(requestOptions);
```
The `login()` method returns a promise which resolves to a `LoginResult`:
The `login()` method returns a promise which resolves to an `Account`. Please see
the result type for [`signup()`](#signup) for details.
#### Onboard
The `onboard()` method presents a choice menu between _Signup_, _Login_, and
_Connect Ledger_ to the user and is thus a general purpose onboarding method.
Just like the direct methods, it only requires a simple request object:
```javascript
interface LoginResult {
walletId: string; // Automatically generated account (wallet) ID
label: string; // The label/name given to the account by the user
const requestOptions = {
// The name of your app, should be as short as possible.
appName: 'Nimiq Safe',
};
type: WalletType; // 0 for in-browser single-address accounts,
// 1 for in-browser multi-address accounts,
// 2 for Ledger hardware accounts
accounts: Array<{ // Array of active addresses detected during login
address: string; // Human-readable address
label: string; // Label/name given by the user
}>;
}
// All client requests are async and return a promise
const account = await accountsClient.onboard(requestOptions);
```
<!-- IDEA should we use std JS Array notation in the doc?
Or do we officially switch to TS? Then that's another section of the
general doc to add on this IMO. -->
Since `onboard()` is a wrapper around Signup, Login and Ledger, it also returns an
`Account` result type. Please see the result type for [`signup()`](#signup) for details.

@@ -383,4 +415,4 @@ #### Logout

The `logout()` method removes an account from the **Accounts Manager**. During the
logout process, the user can retrieve the *Login File* or *Recovery Words*
before the account is deleted.
logout process, the user can export the *Login File* or *Recovery Words* before
the account is deleted.

@@ -392,4 +424,4 @@ ```javascript

// The ID of the account (wallet) that should be removed
walletId: 'xxxxxxxx',
// The ID of the account that should be removed
accountId: 'xxxxxxxx',
};

@@ -405,10 +437,5 @@

```javascript
{
success: true
}
{ success: true }
```
<!-- TODO awaiting final decision on "simple return type" for API methods that
don't really return anything -->
#### Export

@@ -424,4 +451,4 @@

// The ID of the account (wallet) to export
walletId: 'xxxxxxxx',
// The ID of the account to export
accountId: 'xxxxxxxx',
};

@@ -433,14 +460,156 @@

The `export()` method returns a promise which resolves to a simple object
The `export()` method returns a promise which resolves to an object that
contains flags for each export type:
```javascript
interface ExportResult {
fileExported: boolean;
wordsExported: boolean;
}
```
#### Change Password
With the `changePassword()` method, a user can change the password of an account:
```javascript
const requestOptions = {
// The name of your app, should be as short as possible.
appName: 'Nimiq Safe',
// The ID of the account whose password should be changed
accountId: 'xxxxxxxx',
};
// All client requests are async and return a promise
const result = await accountsClient.changePassword(requestOptions);
```
The `changePassword()` method returns a promise which resolves to a simple object
containing the `success` property, which is always true:
```javascript
{
success: true
{ success: true }
```
#### Add Address
By using the `addAddress()` method, the user is able to derive and add an additional
address to their account. The method returns the added address and its label.
The method takes a simple request object as its argument:
```javascript
const requestOptions = {
// The name of your app, should be as short as possible.
appName: 'Nimiq Safe',
// The ID of the account to which an address should be added
accountId: 'xxxxxxxx',
};
// All client requests are async and return a promise
const address = await accountsClient.addAddress(requestOptions);
```
The request's result contains an address string as `address` and a `label`:
```javascript
interface Address {
address: string; // Human-readable address
label: string; // The address's label (name)
}
```
<!-- TODO awaiting final decision on "simple return type" for API methods that
don't really return anything -->
#### Rename
To rename a user's account or addresses, you can call the `rename()` method. The
UI for the rename action always presents the given account and all its addresses
to the user. By sending an optional address with the request, that address's label
will be already pre-selected for the user.
This method takes the following request object as its only argument:
```javascript
const requestOptions = {
// The name of your app, should be as short as possible.
appName: 'Nimiq Safe',
// The ID of the account which should be renamed, or to which the
// address, which should be renamed, belongs
accountId: 'xxxxxxxx',
// [optional] The human-readable address which should be pre-selected
// for the user to be renamed
address: 'NQxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx';
};
// All client requests are async and return a promise
const account = await accountsClient.rename(requestOptions);
```
Since more than one label can be renamed during the rename request, the result
contains the whole account, including all visible addresses. Please see the
result type for [`signup()`](#signup) for details about the `Account` object.
#### Sign Message
To let the user sign an arbitrary message with any of their addresses, you can
call `signMessage()` with the following request object. If you do not include
_both_ the `accountId` _and_ `signer` properties, the user will be prompted to
select an address from their available accounts. The message can be either a
string or a Uint8Array byte array.
```javascript
const requestOptions = {
// The name of your app, should be as short as possible.
appName: 'Nimiq Safe',
// The message to sign. Can either be string of valid UTF-8 or a
// byte array to sign arbitrary data
message: 'String to sign' || new Uint8Array([...]),
// [optional] The ID of the account with which to sign
accountId: 'xxxxxxxx',
// [optional] The human-readable address with which to sign
signer: 'NQxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx';
};
// All client requests are async and return a promise
const signedMessage = await accountsClient.signMessage(requestOptions);
```
The method returns a `SignedMessage` object containing the following properties:
```javascript
interface SignedMessage {
signer: string; // Userfriendly address
signerPublicKey: Uint8Array; // The public key of the signer
signature: Uint8Array; // Signature for the message
message: string | Uint8Array; // The signed message (as the same type as it
// was handed in)
}
```
**Note:** To prevent users from signing valid transactions or other
blockchain-related proofs which could be used to impersonate them, the Nimiq
Keyguard prefixes the string `'Nimiq Signed Message: '` (22 one-byte-characters)
to the input message. The signature is then created over the combined message.
The prefix is already included in the result's `message` property.
Verifying a signed message could go like this:
```javascript
const signature = new Nimiq.Signature(signedMessage.signature);
const publicKey = new Nimiq.PublicKey(signedMessage.signerPublicKey);
const message = typeof signedMessage.message === 'string'
? Nimiq.BufferUtils.fromUtf8(signedMessage.message))
: signedMessage.message;
// Check signature against the message
const isValid = signature.verify(publicKey, message);
```
### Listening for redirect responses

@@ -451,3 +620,3 @@

follow the four steps below to specifically listen for the redirects from the
**Accounts Manager** back to your site using the `on()` method.
**Accounts Manager** back to your site, using the `on()` method.

@@ -474,8 +643,6 @@ Your handler functions will be called with two parameters: the result object and

// 3. Listen for the redirect responses you expect
const RequestType = AccountsClient.RequestType;
accountsClient.on(AccountsClient.RequestType.CHECKOUT, onSuccess, onError);
accountsClient.on(AccountsClient.RequestType.SIGN_TRANSACTION, onSuccess, onError);
accountsClient.on(AccountsClient.RequestType.LOGIN, onSuccess, onError);
accountsClient.on(RequestType.CHECKOUT, onSuccess, onError);
accountsClient.on(RequestType.SIGN_TRANSACTION, onSuccess, onError);
accountsClient.on(RequestType.LOGIN, onSuccess, onError);
// 4. After setup is complete, check for a redirect response

@@ -500,4 +667,9 @@ accountsClient.checkRedirectResponse();

LOGIN = 'login',
ONBOARD = 'onboard',
LOGOUT = 'logout',
EXPORT = 'export',
CHANGE_PASSWORD = 'change-password',
ADD_ADDRESS = 'add-address',
RENAME = 'rename',
SIGN_MESSAGE = 'sign-message',
}

@@ -510,2 +682,5 @@ ```

If you want to run your own instance of Accounts Manager, you also need to run
an instance of the [Keyguard](https://github.com/nimiq/keyguard-next/).
## Contribute

@@ -546,3 +721,3 @@

```bash
yarn run test:unit
yarn run test
```

@@ -557,1 +732,18 @@

```
### Configuration
The following values can be changed via configuration files:
- keyguardEndpoint: The location of your keyguard instance.
- network: The network you want to use. Possible values are 'main', 'test' and
'dev'. You can use the constants (see default configs).
- networkEndpoint: The location of the network iframe instance you want to use.
- privilegedOrigins: An array of origins with special access rights, nameley
permission to use iframe methods like `list()`.
The default config file is `config.local.ts`. To use a different file
(especially useful for deployment), set an environment variable
`build`. E.g. `export build='testnet'` to use `config.testnet.ts`. To set
environment variables permanently, please refer to your server's documentation,
e.g. [for Apache](https://httpd.apache.org/docs/2.4/env.html).
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc