@simbachain/libsimba-js
Version:
libsimba-js is a library simplifying the use of SIMBAChain APIs. We aim to abstract away the various blockchain concepts, reducing the necessary time needed to get to working code.
536 lines (465 loc) • 25.2 kB
HTML
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../">
<title data-ice="title">src/simba/simbabase.js | libsimba-js</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="Simbachain Blockchain abstraction and interaction library"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="libsimba-js"><meta property="twitter:description" content="Simbachain Blockchain abstraction and interaction library"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<a href="test.html" data-ice="testLink">Test</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/simbachain/libsimba-js"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~BadMetadataException.html">BadMetadataException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~BaseException.html">BaseException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~GenerateTransactionException.html">GenerateTransactionException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~GetRequestException.html">GetRequestException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~GetTransactionsException.html">GetTransactionsException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~MethodCallValidationMetadataException.html">MethodCallValidationMetadataException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~MissingMetadataException.html">MissingMetadataException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~NotImplementedException.html">NotImplementedException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~NotInBrowserException.html">NotInBrowserException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~RetriesExceededException.html">RetriesExceededException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~SigningException.html">SigningException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~SubmitTransactionException.html">SubmitTransactionException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~TransactionStatusCheckException.html">TransactionStatusCheckException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~UserRejectedSigningException.html">UserRejectedSigningException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~WalletLockedException.html">WalletLockedException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/exceptions.js~WalletNotFoundException.html">WalletNotFoundException</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-getSimbaInstance">getSimbaInstance</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#simba">simba</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/simba/pagedresponse.js~PagedResponse.html">PagedResponse</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/simba/simba.js~Simbachain.html">Simbachain</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/simba/simbabase.js~SimbaBase.html">SimbaBase</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#wallet">wallet</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/wallet/localwallet.js~LocalWallet.html">LocalWallet</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/wallet/pkwallet.js~PKWallet.html">PKWallet</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/wallet/wallet.js~Wallet.html">Wallet</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><h1 data-ice="title">src/simba/simbabase.js</h1>
<pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">import {pollWrapper} from "poll-js";
import {
MissingMetadataException,
NotImplementedException,
BadMetadataException,
MethodCallValidationMetadataException,
GetTransactionsException
} from '../exceptions';
import PagedResponse from "./pagedresponse";
/**
* @interface
* Base class for libsimba API Interaction implementations
*/
export default class SimbaBase {
/**
* Base class for libsimba API Interaction implementations
* @param {string} endpoint - The endpoint of the API
* @param {Wallet} [wallet] - an optional {@link Wallet} instance
*/
constructor(endpoint, wallet) {
if (!endpoint.endsWith('/')) {
this.endpoint = `${endpoint}/`;
} else {
this.endpoint = endpoint;
}
this.wallet = wallet;
this.metadata = {};
if (this.constructor === SimbaBase) {
// Error Type 1. Abstract class can not be constructed.
throw new TypeError('Can not construct abstract class.');
}
if (this.initialize === SimbaBase.prototype.initialize) {
throw new NotImplementedException('Please implement abstract method callMethod.');
}
if (this.callMethod === SimbaBase.prototype.callMethod) {
throw new NotImplementedException('Please implement abstract method callMethod.');
}
if (this.getTransactionStatus === SimbaBase.prototype.getTransactionStatus) {
throw new NotImplementedException('Please implement abstract method getTransactionStatus.');
}
if (this.checkTransactionStatusFromObject === SimbaBase.prototype.checkTransactionStatusFromObject) {
throw new NotImplementedException('Please implement abstract method checkTransactionStatusFromObject.');
}
if (this.checkTransactionDone === SimbaBase.prototype.checkTransactionDone) {
throw new NotImplementedException('Please implement abstract method checkTransactionDone.');
}
if (this.checkTransactionStatus === SimbaBase.prototype.checkTransactionStatus) {
throw new NotImplementedException('Please implement abstract method checkTransactionStatus.');
}
if (this.getBalance === SimbaBase.prototype.getBalance) {
throw new NotImplementedException('Please implement abstract method getBalance.');
}
if (this.addFunds === SimbaBase.prototype.addFunds) {
throw new NotImplementedException('Please implement abstract method addFunds.');
}
if (this.getMethodTransactions === SimbaBase.prototype.getMethodTransactions) {
throw new NotImplementedException('Please implement abstract method getMethodTransactions.');
}
if (this.getTransaction === SimbaBase.prototype.getTransaction) {
throw new NotImplementedException('Please implement abstract method getTransaction.');
}
if (this.getTransactions === SimbaBase.prototype.getTransactions) {
throw new NotImplementedException('Please implement abstract method getTransactions.');
}
if (this.getBundleMetadataForTransaction === SimbaBase.prototype.getBundleMetadataForTransaction) {
throw new NotImplementedException('Please implement abstract method getBundleMetadataForTransaction.');
}
if (this.getBundleForTransaction === SimbaBase.prototype.getBundleForTransaction) {
throw new NotImplementedException('Please implement abstract method getBundleForTransaction.');
}
if (this.getFileFromBundleForTransaction === SimbaBase.prototype.getFileFromBundleForTransaction) {
throw new NotImplementedException('Please implement abstract method getFileFromBundleForTransaction.');
}
if (this.getFileFromBundleByNameForTransaction === SimbaBase.prototype.getFileFromBundleByNameForTransaction) {
throw new NotImplementedException('Please implement abstract method getFileFromBundleByNameForTransaction.');
}
if (this.sendTransactionRequest === SimbaBase.prototype.sendTransactionRequest) {
throw new NotImplementedException('Please implement abstract method sendTransactionRequest.');
}
}
/**
* @abstract
* (Abstract) Perform any asynchronous actions needed to initialise this class
*/
initialize() {
throw new NotImplementedException('SimbaBase.initialize Not Implemented');
}
/**
* @abstract
* (Abstract) Call a method on the API
* @param {string} method - the method to call
* @param {Object} parameters - the parameters for the method
* @return {Promise} - a promise resolving with the transaction details
*/
callMethod(method, parameters) {
throw new NotImplementedException('SimbaBase.callMethod Not Implemented');
}
/**
* @abstract
* (Abstract) Gets a paged list of transactions for the method
* @param {string} method - The method
* @param {Object} parameters - The query parameters
*/
getMethodTransactions(method, parameters) {
throw new NotImplementedException('SimbaBase.callMethod Not Implemented');
}
/**
* @abstract
* (Abstract) Gets a specific transaction
* @param {string} transactionIdOrHash - Either a transaction ID or a transaction hash
* @returns {Promise<Object>} - The transaction
*/
getTransaction(transactionIdOrHash) {
throw new NotImplementedException('SimbaBase.getTransaction Not Implemented');
}
/**
* @abstract
* (Abstract) Gets a the bundle metadata for a transaction
* @param {string} transactionIdOrHash - Either a transaction ID or a transaction hash
* @returns {Promise<Object>} - The bundle metadata
*/
getBundleMetadataForTransaction(transactionIdOrHash) {
throw new NotImplementedException('SimbaBase.getTransaction Not Implemented');
}
/**
* @abstract
* (Abstract) Gets the bundle for a transaction
* @param {string} transactionIdOrHash - Either a transaction ID or a transaction hash
* @param {boolean} stream - If true, returns a {@link ReadableStream}, otherwise returns a {@link Blob}
* @returns {Promise<ReadableStream|Blob>} - The bundle
*/
getBundleForTransaction(transactionIdOrHash, stream) {
throw new NotImplementedException('SimbaBase.getTransaction Not Implemented');
}
/**
* @abstract
* (Abstract) Gets a file from the bundle for a transaction
* @param {string} transactionIdOrHash - Either a transaction ID or a transaction hash
* @param {number} fileIdx - The index of the file in the bundle metadata
* @param {boolean} stream - If true, returns a {@link ReadableStream}, otherwise returns a {@link Blob}
* @returns {Promise<ReadableStream|Blob>} - The file
*/
getFileFromBundleForTransaction(transactionIdOrHash, fileIdx, stream) {
throw new NotImplementedException('SimbaBase.getTransaction Not Implemented');
}
/**
* @abstract
* (Abstract) Gets a file from the bundle for a transaction
* @param {string} transactionIdOrHash - Either a transaction ID or a transaction hash
* @param {string} fileName - The name of the file in the bundle metadata
* @param {boolean} stream - If true, returns a {@link ReadableStream}, otherwise returns a {@link Blob}
* @returns {Promise<ReadableStream|Blob>} - The file
*/
getFileFromBundleByNameForTransaction(transactionIdOrHash, fileName, stream) {
throw new NotImplementedException('SimbaBase.getTransaction Not Implemented');
}
/**
* @abstract
* (Abstract) Gets a paged list of transactions
* @param {Object} parameters - The query parameters
* @returns {Promise<PagedResponse>} - A response wrapped in a {@link PagedResponse} helper
*/
getTransactions(parameters) {
throw new NotImplementedException('SimbaBase.callMethod Not Implemented');
}
/**
* @abstract
* Internal function for sending transaction GET requests
* @param {URL} url - The URL
* @returns {Promise<PagedResponse>} - A response wrapped in a {@link PagedResponse} helper
*/
async sendTransactionRequest(url){
throw new NotImplementedException('SimbaBase.sendTransactionRequest Not Implemented');
}
/**
* @abstract
* (Abstract) Call a method on the API with files
* @param {string} method - the method to call
* @param {Object} parameters - the parameters for the method
* @param {Array<Blob|File>} files - the files
* @return {Promise<Object>} - a promise resolving with the transaction details
*/
callMethodWithFile(method, parameters, files) {
throw new NotImplementedException('SimbaBase.callMethod Not Implemented');
}
/**
* @abstract
* (Abstract) Get the status of a transaction by ID
* @param {string} txnId - the transaction ID
* @return {Promise<Object>} - a promise resolving with the transaction details
*/
getTransactionStatus(txnId){
throw new NotImplementedException('SimbaBase.getTransactionStatus Not Implemented');
}
/**
* @abstract
* @private
* (Abstract) Gets the status of a transaction
* @param {Object} txn - a transaction object
* @return {Object} - an object with status details
*/
checkTransactionStatusFromObject(txn){
throw new NotImplementedException('SimbaBase.checkTransactionStatusFromObject Not Implemented');
}
/**
* @abstract
* @private
* (Abstract) Check if the transaction is complete
* @param {Object} txn - the transaction object
* @return {boolean} - is the transaction complete
*/
checkTransactionDone(txn){
throw new NotImplementedException('SimbaBase.checkTransactionDone Not Implemented');
}
/**
* @abstract
* (Abstract) Gets the status of a transaction by ID
* @param {string} txnId - a transaction ID
* @return {Object} - an object with status details
*/
checkTransactionStatus(txnId){
throw new NotImplementedException('SimbaBase.checkTransactionStatus Not Implemented');
}
/**
* @abstract
* (Abstract) Get the balance for the attached Wallet
* @return {Promise<Object>} - the balance
*/
getBalance(){
throw new NotImplementedException('SimbaBase.getBalance Not Implemented');
}
/**
* @abstract
* (Abstract) Add funds to the attached Wallet.
* Please check the output of this method. It is of the form
* ```
* {
* txnId: null,
* faucet_url: null,
* poa: true
* }
* ```
*
* If successful, txnId will be populated.
* If the network is PoA, then poa will be true, and txnId will be null
* If the faucet for the network is external (e.g. Rinkeby, Ropsten, etc), then txnId will be null,
* and faucet_url will be populated with a URL. You should present this URL to your users to direct them
* to request funds there.
* @return {Promise<Object>} - details of the txn
*/
addFunds(){
throw new NotImplementedException('SimbaBase.addFunds Not Implemented');
}
/**
* Returns an object with 'future' and 'cancel' keys.
* future is the promise to listen on for the response or an error.
* cancel is a function - call it to cancel the polling.
* @param {string} txnId - the transaction ID
* @param {number} [pollInterval=5000] - the interval in ms for polling
*/
waitForSuccessOrError(txnId, pollInterval){
if(!pollInterval) pollInterval = 5000;
return pollWrapper({
request: () => this.getTransactionStatus(txnId),
pollingPeriod: pollInterval, // ms
shouldStop: (txn)=> this.checkTransactionDone(this.checkTransactionStatusFromObject(txn))
});
}
/**
* Set the wallet
* @param {Wallet} wallet - the wallet
*/
setWallet(wallet){
this.wallet = wallet;
}
/**
* Set the API Key to authenticate calls
* @param {string} apiKey - the API Key
*/
setApiKey(apiKey){
this.apiKey = apiKey;
}
/**
* Set the API Key to authenticate management calls
* @param {string} managementKey - the management API Key
*/
setManagementKey(managementKey){
this.managementKey = managementKey;
}
/**
* @private
* Get API Call auth headers
* @returns {{APIKEY: *, "Content-Type": string}}
*/
apiAuthHeaders() {
return {
APIKEY: this.apiKey,
}
}
/**
* @private
* Get management API Call auth headers
* @returns {{APIKEY: *, "Content-Type": string}}
*/
managementAuthHeaders() {
return {
APIKEY: this.managementKey,
}
}
/**
* @private
* Validate the method call against the app metadata
* @param {string} methodName - the methods name
* @param {Object} parameters - the parameters for the method call
* @param {Array} [files] - Optional array of files
* @returns {boolean}
* @throws {MissingMetadataException} - App Metadata not yet retrieved
* @throws {BadMetadataException} - App Metadata doesn't have methods
* @throws {MethodCallValidationMetadataException} - Method call fails validation
*/
validateCall(methodName, parameters, files){
if (!this.metadata) {
throw new MissingMetadataException("App Metadata not yet retrieved");
}
if (!this.metadata.methods) {
throw new BadMetadataException("App Metadata doesn't have methods!");
}
if(!(methodName in this.metadata.methods)){
throw new MethodCallValidationMetadataException(`Method "${methodName}" not found`);
}
let methodMeta = this.metadata.methods[methodName];
if(files && !('_files' in methodMeta.parameters)){
throw new MethodCallValidationMetadataException(`Method "${methodName}" does not accept files`);
}
if(parameters['_files']){
throw new MethodCallValidationMetadataException(`Files must not be passed in through the parameters argument`);
}
if(files){
for(let i = 0; i < files.length; i++){
if(!(files[i] instanceof Blob) || !(files[i] instanceof File)){
throw new MethodCallValidationMetadataException(`Item at position ${i} of "files" is not a Blob or a File`);
}
}
}
let paramNames = Object.keys(parameters);
paramNames.forEach((key)=>{
if(!(key in methodMeta.parameters)){
throw new MethodCallValidationMetadataException(`Parameter "${key}" is not valid for method "${methodName}"`);
}
//TODO: Type checks
});
//We expect _files to be missing, as it's passed separately
let missing = Object.keys(methodMeta.parameters).filter((key)=>paramNames.indexOf(key) < 0 && key !== '_files');
if(missing.length){
throw new MethodCallValidationMetadataException(`Parameters [${missing.join(',')}] not present for method "${methodName}"`);
}
return true;
}
/**
* @private
* Validate the transaction list call against the app metadata
* @param {string} methodName - the methods name
* @param {Object} parameters - the parameters for the query
* @returns {boolean}
* @throws {MissingMetadataException} - App Metadata not yet retrieved
* @throws {BadMetadataException} - App Metadata doesn't have methods
* @throws {MethodCallValidationMetadataException} - Method call fails validation
*/
validateGetCall(methodName, parameters){
if (!this.metadata) {
throw new MissingMetadataException("App Metadata not yet retrieved");
}
if (!this.metadata.methods) {
throw new BadMetadataException("App Metadata doesn't have methods!");
}
if(!(methodName in this.metadata.methods)){
throw new MethodCallValidationMetadataException(`Method "${methodName}" not found`);
}
return true;
}
/**
* @private
* Validate the transaction list call against the app metadata
* @returns {boolean}
* @throws {MissingMetadataException} - App Metadata not yet retrieved
* @throws {BadMetadataException} - App Metadata doesn't have methods
*/
validateAnyGetCall(){
if (!this.metadata) {
throw new MissingMetadataException("App Metadata not yet retrieved");
}
if (!this.metadata.methods) {
throw new BadMetadataException("App Metadata doesn't have methods!");
}
return true;
}
}
</code></pre>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>