@tangany/waas
Advanced tools
Comparing version 1.1.0 to 1.2.0
# Changelog | ||
All notable changes to this project will be documented in this file. | ||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres | ||
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
## [Unreleased] | ||
### Fixed | ||
### Added | ||
### Changed | ||
## [1.2.0] | ||
### Fixed | ||
### Added | ||
* Add wallet replace functionality (#52) | ||
* Support [WaaS 1.7](https://github.com/Tangany/Wallet-as-a-Service/blob/master/CHANGELOG.md#170---2020-12-22) (#49) | ||
* Return total wallets statistic and wallet public key | ||
* Add payload signing and verification | ||
* Support integer values besides levels in transaction confirmation options | ||
* Make smart contract inputs more flexible and optional | ||
* Add smart contract event search based on their arguments | ||
* Extend transaction search options | ||
* Add asynchronous Bitcoin transactions | ||
### Changed | ||
## [1.1.0] | ||
### Fixed | ||
### Added | ||
* Supporting [WaaS 1.6](https://github.com/Tangany/Wallet-as-a-Service/blob/master/CHANGELOG.md#161---2020-08-12): | ||
@@ -19,47 +45,72 @@ * Call arbitrary readonly smart contract methods | ||
* Optional amount argument in all sending Ethereum methods | ||
### Changed | ||
* Universal smart contract methods `sendAsync` and `estimateFee` allow JavaScript values in `inputs` instead of exclusively string encapsulated values | ||
## [1.0.0] | ||
### Fixed | ||
### Added | ||
* Supporting [WaaS 1.5](https://tangany.com/blog/release-notes-1-5/): | ||
* Options to set custom values for the amount of gas or nonce | ||
* Fee estimation for Ethereum (including the universal smart contract interface) | ||
* Explore Ethereum transactions with combinations of predefined filters | ||
* Explore Ethereum smart contract events | ||
* Get status information about the Ethereum or Bitcoin full node | ||
* Options to set custom values for the amount of gas or nonce | ||
* Fee estimation for Ethereum (including the universal smart contract interface) | ||
* Explore Ethereum transactions with combinations of predefined filters | ||
* Explore Ethereum smart contract events | ||
* Get status information about the Ethereum or Bitcoin full node | ||
* Added `wait` method for asynchronous requests | ||
### Changed | ||
## [1.0.0-beta.9] | ||
### Fixed | ||
* Fixed undefined hash parameter in ethereum transaction status request | ||
### Added | ||
### Changed | ||
## [1.0.0-beta.8] | ||
### Fixed | ||
* Fixed invalid ethereum data string in a failing E2E test | ||
### Added | ||
* Supporting [WaaS 1.4](https://tangany.com/blog/release-notes-1-4/): | ||
* Ethereum and Bitcoin signing | ||
* Asynchronous sending and request status | ||
* Universal Ethereum smart contracts | ||
* `ethereumGasPrice` & `useGasTank` header | ||
* Ethereum and Bitcoin signing | ||
* Asynchronous sending and request status | ||
* Universal Ethereum smart contracts | ||
* `ethereumGasPrice` & `useGasTank` header | ||
### Changed | ||
## [1.0.0-beta.7] | ||
### Fixed | ||
* Fixed the `Wallet` interface throwing a GeneralError instead of ConflictError on wallet naming conflicts | ||
### Added | ||
* Added [E2E code examples](./test/wallet.e2e.js) for a WaaS Wallet based workflow | ||
### Changed | ||
## [1.0.0-beta.6] | ||
### Fixed | ||
### Added | ||
### Changed | ||
* Renamed the npm package to `@tangany/waas` & deprecated the old package `@tangany/waas-js-sdk` | ||
* Allow omitting all `Waas` arguments and authenticate through environment variables TANGANY_CLIENT_ID`, `TANGANY_CLIENT_SECRET`, `TANGANY_SUBSCRIPTION` & `TANGANY_VAULT_URL` | ||
* Allow omitting all `Waas` arguments and authenticate through environment variables TANGANY_CLIENT_ID`, `TANGANY_CLIENT_SECRET`, ` | ||
TANGANY_SUBSCRIPTION` & `TANGANY_VAULT_URL` | ||
* 🚨 Breaking: Removed the AxiosResponse layer from all endpoints. All calls now return the HTTP response data instead of the AxiosResponse type | ||
@@ -69,17 +120,28 @@ * 🚨 Breaking: Drop support for Node.js below version 8.6 | ||
## [1.0.0-beta.5] | ||
### Fixed | ||
* Moved unproductive package (moxios) to devDependencies | ||
## [1.0.0-beta.4] | ||
### Fixed | ||
* Fixed the issue where each daisy-chained subclass of WaaS maintained its own exclusive limiter instance | ||
### Added | ||
* Added methods for fetching affinity cookies | ||
* Added sending data from EthereumWallet | ||
* Added `ethereumTxConfirmations` option | ||
### Changed | ||
* 🚨 Breaking: changed accepted function arguments in `EthErc20Wallet.send`, `EthErc20Wallet.approve`, `EthErc20Wallet.transferFrom`, `EthErc20Wallet.burn` & `EthErc20Wallet.mint` to accept object-type argument matching the style of `BitcoinWallet.send` &`EthereumWallet.send` | ||
* 🚨 Breaking: changed accepted function arguments in `EthErc20Wallet.send`, `EthErc20Wallet.approve`, `EthErc20Wallet.transferFrom` | ||
, `EthErc20Wallet.burn` & `EthErc20Wallet.mint` to accept object-type argument matching the style of `BitcoinWallet.send` &`EthereumWallet.send` | ||
## [1.0.0-beta.3] | ||
### Added | ||
* Added an optional versioning parameter to the constructor | ||
@@ -89,16 +151,23 @@ * Added an API throttling limiter per WaaS instance to prevent `429 Too Many Request` errors | ||
## [1.0.0-beta.2] | ||
### Fixed | ||
* Removed tests from the build | ||
## [1.0.0-beta.1] | ||
### Fixed | ||
* Removed sinon from dist dependencies | ||
## [1.0.0-beta.0] | ||
### Added | ||
* Added support for WaaS 1.2 (Full release notes in our [Blog post](https://tangany.com/blog/release-notes-1-2/)) | ||
* Bitcoin support | ||
* Ethereum ERC20 methods `approve`, `transferFrom`, `mint`, `burn` | ||
* Bitcoin support | ||
* Ethereum ERC20 methods `approve`, `transferFrom`, `mint`, `burn` | ||
### Changed | ||
* 🚨 Breaking: changed accepted function arguments in `EthereumWallet.send` to match `BitcoinWallet.send` | ||
@@ -108,2 +177,3 @@ * 🚨 Breaking: main export renamed to "Waas" | ||
## [0.1.0] | ||
Initial release for WaaS 1.1 |
import { BlockchainWallet } from "./blockchain-wallet"; | ||
import { Waas } from "./waas"; | ||
import { IBitcoinTransactionEstimation, ITransmittableTransaction, IRecipient, ITransaction, IWalletBalance, IBitcoinSweepResult } from "./interfaces"; | ||
import { IAsyncBitcoinTransactionOutput, IBitcoinTransactionEstimation, ITransmittableTransaction, IRecipient, ITransaction, IWalletBalance, IBitcoinSweepResult } from "./interfaces"; | ||
import { Request } from "./request"; | ||
@@ -26,2 +26,7 @@ import { Wallet } from "./wallet"; | ||
/** | ||
* Send BTC from the current wallet to the given recipients in an *asynchronous* manner. | ||
* @param recipients - Recipient configuration | ||
*/ | ||
sendAsync(recipients: IRecipient[] | IRecipient): Promise<Request<IAsyncBitcoinTransactionOutput>>; | ||
/** | ||
* Creates an RLP encoded transaction that is already signed and can be manually transmitted | ||
@@ -28,0 +33,0 @@ * to compatible blockchain networks at a later stage. |
@@ -141,2 +141,22 @@ "use strict"; | ||
/** | ||
* Send BTC from the current wallet to the given recipients in an *asynchronous* manner. | ||
* @param recipients - Recipient configuration | ||
*/ | ||
BtcWallet.prototype.sendAsync = function (recipients) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var rawResponse, id; | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.waas.wrap(function () { return _this.waas.instance | ||
.post(_this.baseUrl + "/send-async", _this.getRecipientsData(recipients)); })]; | ||
case 1: | ||
rawResponse = _a.sent(); | ||
id = this.extractRequestId(rawResponse); | ||
return [2 /*return*/, new request_1.Request(this.waas, id)]; | ||
} | ||
}); | ||
}); | ||
}; | ||
/** | ||
* Creates an RLP encoded transaction that is already signed and can be manually transmitted | ||
@@ -143,0 +163,0 @@ * to compatible blockchain networks at a later stage. |
@@ -6,2 +6,3 @@ import { WalletSecurity, WalletVersion } from "./waas"; | ||
declare type Optional<T, K extends keyof T> = Omit<T, K> & Partial<T>; | ||
export declare type SignatureEncoding = "der" | "ieee-p1363"; | ||
export declare type BlockchainTransactionStatuses = "unknown" | "pending" | "confirmed" | "error"; | ||
@@ -31,2 +32,6 @@ declare type NodeStatus = "live" | "unavailable" | "faulty"; | ||
version: string | WalletVersion.LATEST; | ||
public: { | ||
secp256k1: string; | ||
}; | ||
tags: string[]; | ||
} | ||
@@ -37,2 +42,6 @@ /** | ||
export interface IWalletList { | ||
hits: { | ||
total: number; | ||
hsm: number; | ||
}; | ||
list: IWallet[]; | ||
@@ -56,2 +65,9 @@ skiptoken: string; | ||
} | ||
export interface ISignatureResponse { | ||
signature: string; | ||
encoding: SignatureEncoding; | ||
} | ||
export interface ISignatureVerificationResponse { | ||
isValid: boolean; | ||
} | ||
export declare type IBlockchainTransactionStatus = IEthereumTransactionStatus | IBitcoinTransactionStatus; | ||
@@ -94,2 +110,10 @@ /** | ||
/** | ||
* Represents the output of an asynchronous request for Bitcoin transactions | ||
*/ | ||
export interface IAsyncBitcoinTransactionOutput { | ||
hash: string; | ||
blockNr: number | null; | ||
status: string; | ||
} | ||
/** | ||
* Represents a Bitcoin transaction estimation | ||
@@ -134,2 +158,3 @@ */ | ||
}; | ||
export declare type WaasErrorResponse = IWaasError | IAsyncRequestStatus<IWaasError>; | ||
export interface IWaasError { | ||
@@ -181,3 +206,7 @@ statusCode: number; | ||
function: string; | ||
inputs: (boolean | number | string)[]; | ||
/** | ||
* The associated endpoints allow an array of arguments, which may each contain arbitrary JSON-compatible values. | ||
* In order not to lose this flexibility, the type `unknown` is used. | ||
*/ | ||
inputs?: unknown[]; | ||
} | ||
@@ -217,3 +246,3 @@ /** | ||
iserror?: string; | ||
sort?: "value" | "valuedesc" | "blocknr" | "blocknrdesc" | "nonce" | "noncedesc" | "to" | "todesc" | "from" | "fromdesc" | "timestamp" | "timestampdesc"; | ||
sort?: "value" | "valuedesc" | "blocknr" | "blocknrdesc" | "nonce" | "noncedesc" | "to" | "todesc" | "from" | "fromdesc" | "timestamp" | "timestampdesc" | "transactionindex" | "transactionindexdesc"; | ||
limit?: string; | ||
@@ -239,3 +268,23 @@ index?: string; | ||
index?: number; | ||
argumentFilters?: IEventArgumentFilter[]; | ||
} | ||
/** | ||
* Represents a single filter item to search smart contract events based on their arguments. | ||
* All properties are optional because they can be combined depending on the use case. | ||
*/ | ||
export interface IEventArgumentFilter { | ||
/** | ||
* This can be the positional number (e.g. 2) or the name of an event argument (e.g. "from") | ||
*/ | ||
position?: number | string; | ||
/** | ||
* Defines the Solidity type of the event argument. The API-side default is `address`. | ||
*/ | ||
type?: string; | ||
/** | ||
* Defines the argument value to filter by. The associated endpoints allow any JSON-compatible values. | ||
* In order not to lose this flexibility, the type `unknown` is used for array values, which enables arbitrary nesting. | ||
*/ | ||
value?: string | boolean | number | unknown[]; | ||
} | ||
export interface ISearchTxResponse extends ISearchResponse { | ||
@@ -242,0 +291,0 @@ list: ITxListItem[]; |
@@ -1,2 +0,2 @@ | ||
import { ISearchQueryParams, ISearchResponse } from "../interfaces"; | ||
import { IEventArgumentFilter, ISearchQueryParams, ISearchResponse } from "../interfaces"; | ||
import { Waas } from "../waas"; | ||
@@ -44,2 +44,8 @@ /** | ||
export declare function wrapSearchRequestIterable<TDetail, TData>(waas: Waas, url: string, params?: ISearchQueryParams): ISearchResultIterable<TDetail, TData>; | ||
/** | ||
* Assembles a URL query string to filter events based on their arguments. | ||
* This way, a JavaScript-side configuration with objects is built into a URL string compatible with WaaS. | ||
* @param argFilters - Configured event argument filters | ||
*/ | ||
export declare function composeEventArgumentQuery(argFilters: IEventArgumentFilter[]): string; | ||
export {}; |
@@ -110,2 +110,7 @@ "use strict"; | ||
} | ||
// Build a custom query string for event argument filters due to its custom format | ||
if ("argumentFilters" in queryParams && queryParams.argumentFilters !== undefined) { | ||
_url += composeEventArgumentQuery(queryParams.argumentFilters); | ||
delete queryParams.argumentFilters; // Remove this property as it is SDK-specific and cannot be processed by the endpoint | ||
} | ||
return [4 /*yield*/, waas.wrap(function () { return waas.instance.get(_url, { params: queryParams }); })]; | ||
@@ -157,2 +162,27 @@ case 1: | ||
exports.wrapSearchRequestIterable = wrapSearchRequestIterable; | ||
/** | ||
* Assembles a URL query string to filter events based on their arguments. | ||
* This way, a JavaScript-side configuration with objects is built into a URL string compatible with WaaS. | ||
* @param argFilters - Configured event argument filters | ||
*/ | ||
function composeEventArgumentQuery(argFilters) { | ||
return argFilters.reduce(function (accumulatedQuery, filter) { | ||
var position = filter.position, type = filter.type, value = filter.value; | ||
if (!(position || type || value)) { | ||
throw new Error("An argument filter object must define at least one criterion"); | ||
} | ||
// If it is the first URL query parameter, use "?", otherwise use "&" to join multiple filters | ||
var s = (accumulatedQuery === "" ? "?" : "&") + "inputs"; | ||
// Ensure that the brackets are created to produce the form "inputs[]" even if no position is specified | ||
s += "[" + (position !== undefined ? JSON.stringify(position) : "") + "]"; | ||
if (type) { | ||
s += "." + type; | ||
} | ||
if (value) { | ||
s += "=" + JSON.stringify(value); | ||
} | ||
return accumulatedQuery + s; | ||
}, ""); | ||
} | ||
exports.composeEventArgumentQuery = composeEventArgumentQuery; | ||
//# sourceMappingURL=search-request-wrapper.js.map |
@@ -50,3 +50,3 @@ import { AxiosInstance } from "axios"; | ||
ethereumTxSpeed?: EthereumTxSpeed; | ||
ethereumTxConfirmations?: BlockchainTxConfirmations; | ||
ethereumTxConfirmations?: BlockchainTxConfirmations | number; | ||
ethereumGasPrice?: string; | ||
@@ -57,3 +57,3 @@ ethereumGas?: number; | ||
bitcoinNetwork?: BitcoinNetwork; | ||
bitcoinTxConfirmations?: BlockchainTxConfirmations; | ||
bitcoinTxConfirmations?: BlockchainTxConfirmations | number; | ||
bitcoinTxSpeed?: BitcoinTxSpeed; | ||
@@ -60,0 +60,0 @@ bitcoinMaxFeeRate?: number; |
@@ -154,2 +154,3 @@ "use strict"; | ||
ethereumTxSpeed: "?String", | ||
ethereumTxConfirmations: t.anyOf("?String", "?Number"), | ||
ethereumGasPrice: "?String", | ||
@@ -161,3 +162,3 @@ ethereumGas: "?Number", | ||
bitcoinTxSpeed: "?String", | ||
bitcoinTxConfirmations: "?String", | ||
bitcoinTxConfirmations: t.anyOf("?String", "?Number"), | ||
bitcoinMaxFeeRate: "?Number", | ||
@@ -258,8 +259,8 @@ version: "?Number", | ||
}, function (e) { return __awaiter(_this, void 0, void 0, function () { | ||
var response, message, _a, waasMessage, activityId; | ||
return __generator(this, function (_b) { | ||
if (!e.response) { | ||
var response, message, noErrorDetails, waasError, activityId, waasMessage; | ||
return __generator(this, function (_a) { | ||
response = e.response, message = e.message; | ||
if (!response) { | ||
throw e; | ||
} | ||
response = e.response, message = e.message; | ||
debug("interceptors.response.error", { | ||
@@ -270,4 +271,6 @@ response: response.data, | ||
}); | ||
_a = response.data, waasMessage = _a.message, activityId = _a.activityId; | ||
switch (e.response.status) { | ||
noErrorDetails = { message: "An error has occurred for which no error details could be retrieved", statusCode: 0, activityId: "" }; | ||
waasError = (typeof response.data === "object" && "output" in response.data ? response.data.output : response.data) || noErrorDetails; | ||
activityId = waasError.activityId, waasMessage = waasError.message; | ||
switch (response.status) { | ||
case 401: | ||
@@ -274,0 +277,0 @@ throw new errors_1.AuthenticationError(waasMessage, activityId); |
import { BtcWallet } from "./btc-wallet"; | ||
import { EthWallet } from "./eth-wallet"; | ||
import { ISoftDeletedWallet, IWallet, IWalletList } from "./interfaces"; | ||
import { ISoftDeletedWallet, IWallet, IWalletList, SignatureEncoding } from "./interfaces"; | ||
import { Waas } from "./waas"; | ||
@@ -31,2 +31,8 @@ import { IWaasMethod } from "./waas-method"; | ||
/** | ||
* Creates a new version of the current wallet. It generates new keys and therefore disables "write" operations of the previous wallet version to the blockchain. | ||
* @param [useHsm] - Use a hardware secure module to store the wallet private key | ||
* @see [docs]{@link https://docs.tangany.com/#73451025-c889-4d94-b424-fbe2a3f9999f} | ||
*/ | ||
replace(useHsm?: boolean): Promise<IWallet>; | ||
/** | ||
* Soft-deletes a wallet so not writing operations cannot be executed for the associated blockchain account. Wallet recovery endpoints are not yet implemented into the API. Contact the support team to recover soft-deleted wallets during the retention period. | ||
@@ -42,2 +48,18 @@ * @see [docs]{@link https://docs.tangany.com/#e0b207c8-5cdc-4dce-af6d-a6a655a1cf20} | ||
/** | ||
* Signs the SHA2-256 hash of the given payload string using the ES256K algorithm. | ||
* If a format is specified, the signature is encoded with it, otherwise DER is used by default. | ||
* The result is then returned as base64 text. | ||
* @param payload - Payload string to be signed | ||
* @param [encoding] - Signature encoding to be used (`der` or `ieee-p1363`), where `der` is the default | ||
*/ | ||
sign(payload: string, encoding?: SignatureEncoding): Promise<string>; | ||
/** | ||
* Verifies the SHA2-256 hash of the passed payload string against the given signature. | ||
* By default, the signature is expected in DER format, but the encoding used can also be passed explicitly. | ||
* @param payload - Payload to be compared against the passed signature | ||
* @param signature - Signature to be verified | ||
* @param [encoding] - Encoding used for the passed signature (`der` by default) | ||
*/ | ||
verifySignature(payload: string, signature: string, encoding?: SignatureEncoding): Promise<boolean>; | ||
/** | ||
* Returns wallet calls for the Ethereum blockchain | ||
@@ -44,0 +66,0 @@ */ |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -99,2 +110,16 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
/** | ||
* Creates a new version of the current wallet. It generates new keys and therefore disables "write" operations of the previous wallet version to the blockchain. | ||
* @param [useHsm] - Use a hardware secure module to store the wallet private key | ||
* @see [docs]{@link https://docs.tangany.com/#73451025-c889-4d94-b424-fbe2a3f9999f} | ||
*/ | ||
Wallet.prototype.replace = function (useHsm) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
t("?Boolean", useHsm); | ||
return [2 /*return*/, this.waas.wrap(function () { return _this.waas.instance.put("wallet/" + _this.wallet, { useHsm: useHsm }); })]; | ||
}); | ||
}); | ||
}; | ||
/** | ||
* Soft-deletes a wallet so not writing operations cannot be executed for the associated blockchain account. Wallet recovery endpoints are not yet implemented into the API. Contact the support team to recover soft-deleted wallets during the retention period. | ||
@@ -126,2 +151,51 @@ * @see [docs]{@link https://docs.tangany.com/#e0b207c8-5cdc-4dce-af6d-a6a655a1cf20} | ||
/** | ||
* Signs the SHA2-256 hash of the given payload string using the ES256K algorithm. | ||
* If a format is specified, the signature is encoded with it, otherwise DER is used by default. | ||
* The result is then returned as base64 text. | ||
* @param payload - Payload string to be signed | ||
* @param [encoding] - Signature encoding to be used (`der` or `ieee-p1363`), where `der` is the default | ||
*/ | ||
Wallet.prototype.sign = function (payload, encoding) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var body, signature; | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
body = __assign({ payload: payload }, encoding && { encoding: encoding }); | ||
return [4 /*yield*/, this.waas.wrap(function () { return _this.waas.instance | ||
.post("wallet/" + _this.wallet + "/sign", body); })]; | ||
case 1: | ||
signature = (_a.sent()).signature; | ||
return [2 /*return*/, signature]; | ||
} | ||
}); | ||
}); | ||
}; | ||
/** | ||
* Verifies the SHA2-256 hash of the passed payload string against the given signature. | ||
* By default, the signature is expected in DER format, but the encoding used can also be passed explicitly. | ||
* @param payload - Payload to be compared against the passed signature | ||
* @param signature - Signature to be verified | ||
* @param [encoding] - Encoding used for the passed signature (`der` by default) | ||
*/ | ||
Wallet.prototype.verifySignature = function (payload, signature, encoding) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var body, isValid; | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
body = __assign({ payload: payload, | ||
signature: signature }, encoding && { encoding: encoding }); | ||
return [4 /*yield*/, this.waas.wrap(function () { return _this.waas.instance | ||
.post("wallet/" + _this.wallet + "/verify", body); })]; | ||
case 1: | ||
isValid = (_a.sent()).isValid; | ||
return [2 /*return*/, isValid]; | ||
} | ||
}); | ||
}); | ||
}; | ||
/** | ||
* Returns wallet calls for the Ethereum blockchain | ||
@@ -128,0 +202,0 @@ */ |
{ | ||
"name": "@tangany/waas", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "node.js SDK for Tangany Wallet as a Service API", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -69,3 +69,3 @@ <div align="center"> | ||
ethereumNetwork | Public Ethereum network to operate in (`mainnet`, `ropsten`) or private Ethereum network Custom RPC URL for a private Ethereum network to operate in (example: `http://somenetwork.example.org:8540`) | `mainnet` | | ||
ethereumTxConfirmations | Amount of block confirmations required to consider an Ethereum transaction as valid. The levels correspond with following target block confirmations amounts (# of confirmations): `none`: 0, `default`: 1, `secure`: 12 | `default` | | ||
ethereumTxConfirmations | Amount of block confirmations required to consider an Ethereum transaction as valid. Either a numeric value or one of the following levels can be set, each corresponding to a number of target block confirmations: `none`: 0, `default`: 1, `secure`: 12 | `default` | | ||
ethereumTxSpeed | Additional gas fee that is added to the base gas fee for the given Ethereum network to speed up the mining process of the transaction. The usage of `none` value may result in the transaction never gets mined and is only intended to use for custom Ethereum networks that employ zero gas price policies. The speed levels correspond with following Ethereum fees (in gwei): `none`: 0, `slow`: 2, `default`: 5, `fast`: 15 | `default` | | ||
@@ -77,3 +77,3 @@ ethereumGasPrice | Enforces custom base transaction fee in wei. This prevents the dynamic gas price calculation by the network and nullifies `ethereumTxSpeed`. Example: `7000000000` | `auto` | | ||
bitcoinNetwork | Public Bitcoin network name. Supported networks: `bitcoin`, `testnet` | `bitcoin` | | ||
bitcoinTxConfirmations | Minimum amount of block confirmations required for Bitcoin balance outputs ("utxo", "coins") to be included in the total wallet balance calculation. The exclusion of unconfirmed outputs prevents the posthumous invalidation of own wallet transaction by the parent utxo sending party. The levels correspond with following target block confirmations amounts (# of confirmations): `none`: 0, `default`: 1, `secure`: 6 | `default` | | ||
bitcoinTxConfirmations | Minimum amount of block confirmations required for Bitcoin balance outputs ("utxo", "coins") to be included in the total wallet balance calculation. The exclusion of unconfirmed outputs prevents the posthumous invalidation of own wallet transaction by the parent utxo sending party. Either a numeric value or one of the following levels can be set, each corresponding to a number of target block confirmations: `none`: 0, `default`: 1, `secure`: 6 | `default` | | ||
bitcoinTxSpeed | Defines the target amount of blocks for the transaction to be included to the Bitcoin network. Faster inclusion requires a higher transaction fee. The fee is calculated in real time based on the network state and can be limited by the `header-bitcoin-max-fee-rate` option. The effective transaction delay can be calculated by multiplying the target confirmation blocks with the Bitcoin block time of 10 minutes (e.g. `slow` yields an block inclusion time of approx. 4h). The speed levels correspond with following block times (target blocks): `slow`: 24, `default`: 6, `fast`: 2 | `default` | | ||
@@ -96,2 +96,4 @@ bitcoinMaxFeeRate | Defines the maximum allowed fee rate in satoshi per byte for a Bitcoin transaction. Prevents from spending absurdly high transaction fees during block fee peaks | 500 | | ||
const { created } = await api.wallet(wallet).get(); | ||
// replace a wallet | ||
const { version } = await api.wallet(wallet).replace(); | ||
// delete a wallet | ||
@@ -102,2 +104,20 @@ const { scheduledPurgeDate, recoveryId } = await api.wallet(wallet).delete(); | ||
#### Payload signing interface | ||
````javascript | ||
(async () => { | ||
const api = new Waas().wallet("my-wallet"); | ||
const payload = "arbitrary payload"; | ||
// create signature with default encoding (DER) | ||
const signatureDer = await api.sign(payload); | ||
// create signature with IEEE-P1363 encoding | ||
const signatureP1363 = await api.sign(payload, "ieee-p1363"); | ||
// verify signatures | ||
const isValidDer = await waas.verifySignature(payload, signatureDer); | ||
const isValidP1363 = await waas.verifySignature(payload, signatureP1363, "ieee-p1363"); | ||
// DER signatures can also be verified externally using tools such as OpenSSL. | ||
// For this, the public key is necessary, which may have to be converted depending on the tool. | ||
const {public: {secp256k1}} = await api.get(); | ||
})(); | ||
```` | ||
#### General Ethereum interface | ||
@@ -206,2 +226,7 @@ [*Ethereum calls that are not wallet based*](https://docs.tangany.com/#7b314b47-012c-4baa-b928-dd32c7db1e41) | ||
const eventDetails = await eventsList[0].get(); | ||
// Query transaction events based on their arguments | ||
const filteredEventsIterator = await api.contract(tokenAddress).getEvents({ | ||
event: "Transfer", | ||
argumentFilters: [{position: "to", value: "0x1ec2a77ec126369ad7c7e6fdb03e3d52b79b013d"}] | ||
}); | ||
// Read an individual event | ||
@@ -236,2 +261,4 @@ const event = await new Waas().eth(txHash).getEvent(logIndex); | ||
await api.btc().send([{to: someAddress, amount: "0.324"}, {to: someOtherAddress, amount: "0.021"}]); | ||
// send BTC using an asynchronous request | ||
const sendReq = await api.btc().sendAsync([{to: someAddress, amount: "0.324"}, {to: someOtherAddress, amount: "0.021"}]); | ||
// create a signed transaction that can be manually transmitted | ||
@@ -238,0 +265,0 @@ const { rawTransaction } = await api.btc().sign({to: someAddress, amount: "0.021"}); |
@@ -91,2 +91,11 @@ const { Waas, BITCOIN_NETWORK, BITCOIN_TX_CONFIRMATIONS } = require("../dist"); | ||
it("should send some BTC using an asynchronous request", async function () { | ||
const req = await noConfirmationsBtcApi.wallet(wallet).btc().sendAsync(recipients); | ||
// To take advantage of the asynchronous behavior, normally one would not wait for completion. For testing purposes, however, we do. | ||
console.log(`Wait for the completion of request ${req.id} ...`); | ||
await req.wait(35e3); | ||
const { output } = await req.get(); | ||
console.log(output); | ||
}); | ||
it("should transfer all funds from the created wallet back to the main wallet", async function () { | ||
@@ -93,0 +102,0 @@ const req = await noConfirmationsBtcApi.wallet(createdWallet).btc().sweepAsync({wallet: wallet}); |
@@ -119,2 +119,21 @@ const { config } = require("dotenv"); | ||
it("should filter contract events by their arguments", async function () { | ||
const ropstenApi = new Waas({ ethereumNetwork: EthereumPublicNetwork.ROPSTEN }); | ||
const iterable = ropstenApi.eth() | ||
.contract("0xC32AE45504Ee9482db99CfA21066A59E877Bc0e6") | ||
.getEvents({ | ||
event: "Approval", argumentFilters: [ | ||
{ position: "owner", value: "0x76F0CE0Ee55bF1AAe0ADF85A2cd348b8Dd358376" }, | ||
{ position: "spender", value: "0x9C2E011c0CE0d75c2B62B9C5A0Ba0a7456593803" }, | ||
] | ||
}); | ||
const iterator = await iterable[Symbol.asyncIterator]().next(); | ||
const events = iterator.value; | ||
console.log(`${events.hits.total} results found. The first 2 are displayed below:`); | ||
for (const elem of events.list.slice(0, 2)) { | ||
const details = await elem.get(); | ||
console.log(details); | ||
} | ||
}); | ||
it("should read a specific event for given transaction and index", async function () { | ||
@@ -121,0 +140,0 @@ const ropstenApi = new Waas({ ethereumNetwork: EthereumPublicNetwork.ROPSTEN }); |
@@ -27,2 +27,6 @@ const { Waas } = require("../dist"); | ||
// Tangany-based smart contract ("Caller") used for testing here: | ||
// https://github.com/Tangany/truffle-blueprint/blob/master/contracts/Caller.sol | ||
const callerContract = "0x6dfC099FD9D1214e37e33Ecb3124dE451b751EbF"; | ||
const api = new Waas({ | ||
@@ -212,2 +216,30 @@ ethereumNetwork: EthereumPublicNetwork.ROPSTEN, // All tests execute on the ropsten testnet | ||
it("should call a smart contract function with nested array argument", async function () { | ||
const resultArr = await api.eth().contract(callerContract).call({ | ||
"function": "callFlattenAddressArray(address[][2])", | ||
"inputs": [ | ||
[ | ||
[ | ||
"0x0120000000000000000000000000000000000000", | ||
"0x0340000000000000000000000000000000000000" | ||
], | ||
[ | ||
"0x1330000000000000000000000000000000000000", | ||
"0x1440000000000000000000000000000000000000", | ||
"0x1550000000000000000000000000000000000000" | ||
] | ||
] | ||
], | ||
outputs: ["address[]"] | ||
}); | ||
const expected = [ | ||
"0x0120000000000000000000000000000000000000", | ||
"0x0340000000000000000000000000000000000000", | ||
"0x1330000000000000000000000000000000000000", | ||
"0x1440000000000000000000000000000000000000", | ||
"0x1550000000000000000000000000000000000000" | ||
]; | ||
assert.deepStrictEqual(resultArr[0].value, expected); | ||
}); | ||
it("should create a signed transaction that can be manually transmitted", async function () { | ||
@@ -214,0 +246,0 @@ const { rawTransaction } = await api.wallet(tokenWallet).eth().sign({ |
@@ -52,2 +52,30 @@ const { Waas } = require("../dist"); | ||
it("should sign and verify arbitrary payload", async function(){ | ||
assert.ok(createdWallet, "cannot run without previous tests"); | ||
const walletApi = api.wallet(createdWallet); | ||
const payload = "Hello World"; | ||
const signatureDer = await walletApi.sign(payload); | ||
assert.ok(signatureDer); | ||
const isValidDer = await walletApi.verifySignature(payload, signatureDer); | ||
assert.ok(isValidDer); | ||
const signatureP1363 = await walletApi.sign(payload, "ieee-p1363"); | ||
assert.ok(signatureP1363); | ||
const isValidP1363 = await walletApi.verifySignature(payload, signatureP1363, "ieee-p1363"); | ||
assert.ok(isValidP1363); | ||
}); | ||
it("should replace the created wallet with a new version", async function(){ | ||
assert.ok(createdWallet, "cannot run without previous tests"); | ||
const wallet = api.wallet(createdWallet); | ||
const previousWallet = await wallet.get(); | ||
const replacedWallet = await wallet.replace(); | ||
assert.notStrictEqual(replacedWallet.version, previousWallet.version); | ||
assert.strictEqual(replacedWallet.wallet, previousWallet.wallet); | ||
assert.notStrictEqual(replacedWallet.updated, previousWallet.updated); | ||
}); | ||
it("should delete the created wallet", async function () { | ||
@@ -54,0 +82,0 @@ this.timeout(30e3); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
319143
4500
369