├── .gitignore ├── .prettierrc ├── README.md ├── package-lock.json ├── package.json ├── src ├── __tests__ │ ├── __snapshots__ │ │ └── index.test.ts.snap │ ├── index.test.ts │ └── utils.test.ts ├── createRequest.ts ├── index.ts ├── methods │ ├── createMethod.ts │ ├── getAliases.ts │ ├── getAssets.ts │ ├── getAssetsByTicker.ts │ ├── getCandles.ts │ ├── getExchangeTxs.ts │ ├── getMassTransferTxs.ts │ ├── getPairs.ts │ └── getTransferTxs.ts ├── transform.ts ├── types.ts └── utils.ts ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .history 2 | node_modules/ 3 | dist/ 4 | .idea 5 | yarn-error.log 6 | *.sandbox.js 7 | *.sandbox.ts -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 80 7 | } 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JS Library for Waves data services 2 | 3 | ## Usage 4 | 5 | ```typescript 6 | const DataServiceClient = require('@waves/data-service-client-js').default; 7 | 8 | // Initialization 9 | const client = new DataServiceClient({ 10 | rootUrl: 'http://api.wavesplatform.com/v0', 11 | fetch: req => window.fetch(req).then(res => res.text()), // fetch must return string 12 | parse: str => JSON.parse(str), 13 | }); 14 | 15 | // Fetching 16 | (async () => { 17 | const { data } = await client.getAssets('WAVES'); // data: Asset {} 18 | })(); 19 | ``` 20 | 21 | ## Methods 22 | 23 | ### Response format 24 | 25 | `{ data, ...meta }` 26 | 27 | ### All methods do GET requests, until query is under 2k symbols, then automatically switch to POST 28 | 29 | - getAssets: 30 | 31 | ```typescript 32 | await client.getAssets('WAVES'); // One { data: Asset } 33 | await client.getAssets('WAVES', '8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS'); // Or many { data: Asset[] } 34 | await client.getAssetsByTicker('WAVES'); // Many { data: Asset[] } 35 | await client.getAssetsByTicker('*'); // Many { data: Asset[] } - all assets 36 | ``` 37 | 38 | - getPairs 39 | 40 | ```typescript 41 | const getPairs = client.getPairs('MATCHER_ID'); // set up DEX matcher 42 | await getPairs([ 43 | 'WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS', 44 | 'WAVES/474jTeYx2r2Va35794tCScAXWJG9hU2HcgxzMowaZUnu' 45 | ]); // get pairs 46 | ``` 47 | 48 | - getExchangeTxs: 49 | 50 | ```typescript 51 | await client.getExchangeTxs('8rEwYY4wQ4bkEkk95EiyeQnvnonX6TAnU6eiBAbVSADk'); // By id { data: Tx } 52 | await client.getExchangeTxs({ 53 | timeStart?: string | Date | number; 54 | timeEnd?: string | Date | number; 55 | matcher?: string; 56 | sender?: string; 57 | amountAsset?: string | Asset; 58 | priceAsset?: string | Asset; 59 | limit?: number; 60 | sort?: 'asc'|'desc'; 61 | }); // With filters { data: Tx[] } 62 | await client.getExchangeTxs(); // Top 100 with default filters (timeStart = timestamp of first entry in db, timeEnd = now) 63 | ``` 64 | 65 | - aliases: 66 | 67 | ```typescript 68 | const alias1 = await client.aliases.getById('@askerych'); 69 | /* 70 | { data: { 71 | address: '3P5uMgn1xvrm7g3sbUVAGLtetkNUa1AHn2M', 72 | alias: '@askerych' 73 | } 74 | } 75 | */ 76 | const alias2 = await client.aliases.getByAddress( 77 | '3P5uMgn1xvrm7g3sbUVAGLtetkNUa1AHn2M' 78 | ); 79 | /* 80 | { data: [{ 81 | address: '3P5uMgn1xvrm7g3sbUVAGLtetkNUa1AHn2M', 82 | alias: '@askerych' 83 | }] 84 | } 85 | */ 86 | ``` 87 | 88 | - getCandles: 89 | 90 | ```typescript 91 | await client.getCandles(amountAsset: string, priceAsset: string, { 92 | timeStart: string | Date | number; 93 | timeEnd?: string | Date | number; 94 | interval: string; // interval pattern is xy, where x - number, y - one of m (minutes), h (hours), d (days), M (Month) 95 | }); 96 | await client.getCandles('WAVES', '8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS', { 97 | timeStart: '2018-12-01', 98 | timeEnd: '2018-12-31', 99 | interval: '1d' 100 | }); 101 | ``` 102 | 103 | ## Pagination 104 | 105 | ```typescript 106 | type Response = { 107 | data: T; 108 | fetchMore?: TFunction; 109 | }; 110 | const response1 = await client.getExchangeTxs({ limit: 1, sort: 'asc' }); 111 | const data1 = response1.data; 112 | // Process data 113 | 114 | const response2 = await res1.fetchMore(2); // 2 more 115 | ``` 116 | 117 | ## Custom init params 118 | 119 | You can set custom fetcher, parser and transformer for library. 120 | 121 | ```typescript 122 | type TLibOptions = { 123 | rootUrl: string; 124 | fetch?: TFunction; 125 | parse?: TParser; 126 | transform?: TFunction; 127 | }; 128 | ``` 129 | 130 | The path is fetch -> parse -> transform 131 | 132 | ### Fetch must return string! 133 | 134 | Fetch accepts (url, options) 135 | Fetch by default is `fetch(...).then(res => res.text())` 136 | 137 | Parse by default is `JSON.parse.bind(JSON)` , you can use `json-bigint`'s parse if you want to add support for bignumbers. 138 | 139 | Transform function has next signature by default (it depends on your parse function): 140 | 141 | ``` 142 | ({ 143 | __type, 144 | data, 145 | ...rest 146 | }) => any 147 | ``` 148 | 149 | Basically you can switch on \_\_type and do transformations. 150 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@waves/data-service-client-js", 3 | "version": "4.1.1", 4 | "main": "dist/index.js", 5 | "types": "dist/index.d.ts", 6 | "author": "Ivan Shmidt ", 7 | "license": "MIT", 8 | "scripts": { 9 | "dev": "ts-node src/index.ts", 10 | "build": "tsc", 11 | "build:browser:dev": "tsc && browserify ./dist/index.js -o ./dist/umd.js", 12 | "build:browser": "browserify ./dist/index.js -o ./dist/umd.js -u @waves/data-entities -u @waves/bignumber", 13 | "build:all": "rimraf ./dist/* && npm run build && npm run build:browser", 14 | "test": "jest", 15 | "prepare": "npm run build:all && npm test" 16 | }, 17 | "dependencies": { 18 | "@waves/bignumber": "^1.0.0", 19 | "@waves/data-entities": "^2.0.0-a3" 20 | }, 21 | "devDependencies": { 22 | "@types/jest": "^22.2.3", 23 | "@types/node": "8.0.0", 24 | "@types/node-fetch": "^1.6.9", 25 | "browserify": "^16.2.2", 26 | "jest": "^23.6.0", 27 | "node-fetch": "^2.1.2", 28 | "parse-json-bignumber": "^0.0.2", 29 | "rimraf": "^2.6.2", 30 | "ts-jest": "^23.10.5", 31 | "typescript": "^3.4.5" 32 | }, 33 | "jest": { 34 | "transform": { 35 | "^.+\\.tsx?$": "ts-jest" 36 | }, 37 | "testRegex": "(src/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", 38 | "testPathIgnorePatterns": [ 39 | "/node_modules/", 40 | ".history" 41 | ], 42 | "moduleFileExtensions": [ 43 | "ts", 44 | "tsx", 45 | "js", 46 | "jsx", 47 | "json", 48 | "node" 49 | ], 50 | "testURL": "http://localhost/" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/__tests__/__snapshots__/index.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Aliases endpoint: fetch is called with correct params#1 1`] = ` 4 | Array [ 5 | "NODE_URL/aliases?address=address", 6 | Object { 7 | "method": "GET", 8 | }, 9 | ] 10 | `; 11 | 12 | exports[`Aliases endpoint: fetch is called with correct params#1 2`] = ` 13 | Array [ 14 | "NODE_URL/aliases?address=address&showBroken=true", 15 | Object { 16 | "method": "GET", 17 | }, 18 | ] 19 | `; 20 | 21 | exports[`Aliases endpoint: fetch is called with correct params#2 1`] = ` 22 | Array [ 23 | "NODE_URL/aliases/id", 24 | Object { 25 | "method": "GET", 26 | }, 27 | ] 28 | `; 29 | 30 | exports[`Asssets endpoint: fetch is called with correct params#1 1`] = ` 31 | Array [ 32 | "NODE_URL/assets?ids=4CYRBpSmNKqmw1PoKFoZADv5FaciyJcusqrHyPrAQ4Ca&ids=AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa", 33 | Object { 34 | "method": "GET", 35 | }, 36 | ] 37 | `; 38 | 39 | exports[`Asssets endpoint: fetch is called with correct params#2 1`] = ` 40 | Array [ 41 | "NODE_URL/assets?ids=4CYRBpSmNKqmw1PoKFoZADv5FaciyJcusqrHyPrAQ4Ca", 42 | Object { 43 | "method": "GET", 44 | }, 45 | ] 46 | `; 47 | 48 | exports[`Asssets endpoint: fetch is called with correct params#3 1`] = ` 49 | Array [ 50 | "NODE_URL/assets", 51 | Object { 52 | "method": "GET", 53 | }, 54 | ] 55 | `; 56 | 57 | exports[`Asssets endpoint: fetch is called with correct params#4 1`] = ` 58 | Array [ 59 | "NODE_URL/assets?ticker=WAVES", 60 | Object { 61 | "method": "GET", 62 | }, 63 | ] 64 | `; 65 | 66 | exports[`Asssets endpoint: fetch is called with correct params#5 1`] = ` 67 | Array [ 68 | "NODE_URL/assets?ticker=*", 69 | Object { 70 | "method": "GET", 71 | }, 72 | ] 73 | `; 74 | 75 | exports[`Candles endpoint: fetch is called with correct params#1 1`] = ` 76 | Array [ 77 | "NODE_URL/candles/AMOUNTASSETID/PRICEASSETID?timeStart=2018-12-01&timeEnd=2018-12-31&interval=1h&matcher=123", 78 | Object { 79 | "method": "GET", 80 | }, 81 | ] 82 | `; 83 | 84 | exports[`Candles endpoint: fetch is called with correct params#2 1`] = ` 85 | Array [ 86 | "NODE_URL/candles/AMOUNTASSETID/PRICEASSETID?timeStart=2018-12-01&interval=1h&matcher=123", 87 | Object { 88 | "method": "GET", 89 | }, 90 | ] 91 | `; 92 | 93 | exports[`ExchangeTxs endpoint: works with (empty call) 1`] = ` 94 | Array [ 95 | "NODE_URL/transactions/exchange", 96 | Object { 97 | "method": "GET", 98 | }, 99 | ] 100 | `; 101 | 102 | exports[`ExchangeTxs endpoint: works with (single string) 1`] = ` 103 | Array [ 104 | "NODE_URL/transactions/exchange/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS", 105 | Object { 106 | "method": "GET", 107 | }, 108 | ] 109 | `; 110 | 111 | exports[`ExchangeTxs endpoint: works with (with all filters) 1`] = ` 112 | Array [ 113 | "NODE_URL/transactions/exchange?timeStart=2016-02-01&timeEnd=2016-03-01&matcher=matcher&sender=sender&amountAsset=asset1&priceAsset=priceAsset&limit=5&sort=-some", 114 | Object { 115 | "method": "GET", 116 | }, 117 | ] 118 | `; 119 | 120 | exports[`ExchangeTxs endpoint: works with (with one filter) 1`] = ` 121 | Array [ 122 | "NODE_URL/transactions/exchange?timeStart=2016-01-01", 123 | Object { 124 | "method": "GET", 125 | }, 126 | ] 127 | `; 128 | 129 | exports[`Long params transforms into POST request works 1`] = ` 130 | Array [ 131 | "NODE_URL/assets", 132 | Object { 133 | "body": "{\\"ids\\":[\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\",\\"AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa\\"]}", 134 | "headers": Object { 135 | "Accept": "application/json, text/plain, */*", 136 | "Content-Type": "application/json", 137 | }, 138 | "method": "POST", 139 | }, 140 | ] 141 | `; 142 | 143 | exports[`Long params transforms into POST request works for pairs 1`] = ` 144 | Array [ 145 | "NODE_URL/pairs", 146 | Object { 147 | "body": "{\\"pairs\\":[\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\",\\"WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\\"],\\"matcher\\":\\"3PJjwFREg8F9V6Cp9fnUuEwRts6HQQa5nfP\\"}", 148 | "headers": Object { 149 | "Accept": "application/json, text/plain, */*", 150 | "Content-Type": "application/json", 151 | }, 152 | "method": "POST", 153 | }, 154 | ] 155 | `; 156 | 157 | exports[`Pagination: works 1`] = ` 158 | Array [ 159 | Array [ 160 | "NODE_URL/transactions/exchange?sort=asc&limit=1", 161 | Object { 162 | "method": "GET", 163 | }, 164 | ], 165 | Array [ 166 | "NODE_URL/transactions/exchange?sort=asc&limit=1&after=cursor", 167 | Object { 168 | "method": "GET", 169 | }, 170 | ], 171 | ] 172 | `; 173 | 174 | exports[`Pairs endpoint: fetch is called with correct params#1 1`] = ` 175 | Array [ 176 | "NODE_URL/pairs?pairs=WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS&pairs=WAVES/474jTeYx2r2Va35794tCScAXWJG9hU2HcgxzMowaZUnu&matcher=3PJjwFREg8F9V6Cp9fnUuEwRts6HQQa5nfP", 177 | Object { 178 | "method": "GET", 179 | }, 180 | ] 181 | `; 182 | 183 | exports[`Pairs endpoint: fetch is called with correct params#2 1`] = ` 184 | Array [ 185 | "NODE_URL/pairs?&matcher=3PJjwFREg8F9V6Cp9fnUuEwRts6HQQa5nfP", 186 | Object { 187 | "method": "GET", 188 | }, 189 | ] 190 | `; 191 | 192 | exports[`TransferTxs endpoint: works with (empty call) 1`] = ` 193 | Array [ 194 | "NODE_URL/transactions/transfer", 195 | Object { 196 | "method": "GET", 197 | }, 198 | ] 199 | `; 200 | 201 | exports[`TransferTxs endpoint: works with (single string) 1`] = ` 202 | Array [ 203 | "NODE_URL/transactions/transfer/some id", 204 | Object { 205 | "method": "GET", 206 | }, 207 | ] 208 | `; 209 | 210 | exports[`TransferTxs endpoint: works with (with all filters) 1`] = ` 211 | Array [ 212 | "NODE_URL/transactions/transfer?assetId=assetId&sender=sender&recipient=recipient&timeStart=2016-02-01&timeEnd=2016-03-01&limit=5&sort=-some", 213 | Object { 214 | "method": "GET", 215 | }, 216 | ] 217 | `; 218 | 219 | exports[`TransferTxs endpoint: works with (with one filter) 1`] = ` 220 | Array [ 221 | "NODE_URL/transactions/transfer?timeStart=2016-01-01", 222 | Object { 223 | "method": "GET", 224 | }, 225 | ] 226 | `; 227 | -------------------------------------------------------------------------------- /src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | const parser = require('parse-json-bignumber')(); 2 | import DataServiceClient from '../index'; 3 | import { AssetPair, Asset } from '@waves/data-entities'; 4 | 5 | const fetch = jest.fn(() => Promise.resolve('{"data":[{ "data": 1 }]}')); 6 | const NODE_URL = 'NODE_URL'; 7 | const MATCHER = '3PJjwFREg8F9V6Cp9fnUuEwRts6HQQa5nfP'; 8 | const client = new DataServiceClient({ 9 | rootUrl: NODE_URL, 10 | parse: parser, 11 | fetch, 12 | }); 13 | 14 | describe('Asssets endpoint: ', () => { 15 | it('fetch is called with correct params#1', async () => { 16 | const ids = [ 17 | '4CYRBpSmNKqmw1PoKFoZADv5FaciyJcusqrHyPrAQ4Ca', 18 | 'AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa', 19 | ]; 20 | await client.getAssets(...ids); 21 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 22 | }); 23 | 24 | it('fetch is called with correct params#2', async () => { 25 | const ids = ['4CYRBpSmNKqmw1PoKFoZADv5FaciyJcusqrHyPrAQ4Ca']; 26 | await client.getAssets(...ids); 27 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 28 | }); 29 | 30 | it('fetch is called with correct params#3', async () => { 31 | const ids = []; 32 | await client.getAssets(...ids); 33 | 34 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 35 | }); 36 | 37 | it('fetch is called with correct params#4', async () => { 38 | const ticker = 'WAVES'; 39 | await client.getAssetsByTicker(ticker); 40 | 41 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 42 | }); 43 | 44 | it('fetch is called with correct params#5', async () => { 45 | const ticker = '*'; 46 | await client.getAssetsByTicker(ticker); 47 | 48 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 49 | }); 50 | 51 | it('throws, if called with wrong types', async () => { 52 | const wrongTypes: any[] = [1, null, NaN, undefined, {}]; 53 | wrongTypes.map( 54 | async t => await expect(client.getAssets(t)).rejects.toBeDefined() 55 | ); 56 | }); 57 | }); 58 | 59 | describe('Pairs endpoint: ', () => { 60 | it('fetch is called with correct params#1', async () => { 61 | const pair1 = new AssetPair( 62 | 'WAVES' as any, 63 | '8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS' as any 64 | ); 65 | const pair2 = new AssetPair( 66 | 'WAVES' as any, 67 | '474jTeYx2r2Va35794tCScAXWJG9hU2HcgxzMowaZUnu' as any 68 | ); 69 | await client.getPairs('3PJjwFREg8F9V6Cp9fnUuEwRts6HQQa5nfP')([ 70 | pair1, 71 | pair2, 72 | ]); 73 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 74 | }); 75 | 76 | it('fetch is called with correct params#2', async () => { 77 | const pairs = []; 78 | await client.getPairs('3PJjwFREg8F9V6Cp9fnUuEwRts6HQQa5nfP')(pairs); 79 | 80 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 81 | }); 82 | 83 | it('throws, if called with wrong types', async () => { 84 | const wrongTypes: any = [ 85 | 1, 86 | null, 87 | NaN, 88 | undefined, 89 | {}, 90 | { amountAsset: '' }, 91 | { priceAsset: '' }, 92 | '', 93 | ]; 94 | wrongTypes.map( 95 | async t => 96 | await expect( 97 | client.getPairs('3PJjwFREg8F9V6Cp9fnUuEwRts6HQQa5nfP')(t) 98 | ).rejects.toBeDefined() 99 | ); 100 | }); 101 | }); 102 | 103 | describe('Aliases endpoint: ', () => { 104 | it('fetch is called with correct params#1', async () => { 105 | await client.aliases.getByAddress('address'); 106 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 107 | }); 108 | it('fetch is called with correct params#1', async () => { 109 | await client.aliases.getByAddress('address', { showBroken: true }); 110 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 111 | }); 112 | it('fetch is called with correct params#2', async () => { 113 | await client.aliases.getById('id'); 114 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 115 | }); 116 | 117 | it('throws, if called with wrong types', async () => { 118 | const wrongTypes: any = [1, null, NaN, undefined, {}]; 119 | wrongTypes.map(async t => { 120 | await expect(client.aliases.getByAddress(t)).rejects.toBeDefined(); 121 | await expect(client.aliases.getById(t)).rejects.toBeDefined(); 122 | }); 123 | }); 124 | }); 125 | 126 | describe('Candles endpoint: ', () => { 127 | it('fetch is called with correct params#1', async () => { 128 | await client.getCandles('AMOUNTASSETID', 'PRICEASSETID', { 129 | timeStart: '2018-12-01', 130 | timeEnd: '2018-12-31', 131 | interval: '1h', 132 | matcher: '123', 133 | }); 134 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 135 | }); 136 | it('fetch is called with correct params#2', async () => { 137 | await client.getCandles('AMOUNTASSETID', 'PRICEASSETID', { 138 | timeStart: '2018-12-01', 139 | interval: '1h', 140 | matcher: '123', 141 | }); 142 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 143 | }); 144 | it('throws, if called with wrong types', async () => { 145 | const wrongTypes: any = [null, NaN, {}]; 146 | wrongTypes.map(async t => { 147 | await expect(client.getCandles(null, null, null)).rejects.toBeDefined(); 148 | await expect(client.getCandles(null, null, t)).rejects.toBeDefined(); 149 | }); 150 | }); 151 | }); 152 | 153 | describe('ExchangeTxs endpoint: ', async () => { 154 | type Case = { label: string; params: any[]; expectedUrl?: string }; 155 | const goodCases: Case[] = [ 156 | { 157 | label: 'single string', 158 | params: ['8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS'], 159 | expectedUrl: `${NODE_URL}/transactions/exchange/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS`, 160 | }, 161 | { 162 | label: 'empty call', 163 | params: [], 164 | expectedUrl: `${NODE_URL}/transactions/exchange`, 165 | }, 166 | { 167 | label: 'with one filter', 168 | params: [{ timeStart: '2016-01-01' }], 169 | expectedUrl: `${NODE_URL}/transactions/exchange?timeStart=2016-01-01`, 170 | }, 171 | { 172 | label: 'with all filters', 173 | params: [ 174 | { 175 | timeStart: '2016-02-01', 176 | timeEnd: '2016-03-01', 177 | matcher: 'matcher', 178 | sender: 'sender', 179 | amountAsset: 'asset1', 180 | priceAsset: 'priceAsset', 181 | limit: 5, 182 | sort: '-some', 183 | }, 184 | ], 185 | expectedUrl: `${NODE_URL}/transactions/exchange?timeStart=2016-02-01&timeEnd=2016-03-01&matcher=matcher&sender=sender&amountAsset=asset1&priceAsset=priceAsset&limit=5&sort=-some`, 186 | }, 187 | ]; 188 | const badCases: Case[] = [ 189 | { 190 | label: 'with wrong filters', 191 | params: [{ incorrectField: '' }], 192 | }, 193 | { 194 | label: 'with number', 195 | params: [1], 196 | }, 197 | { 198 | label: 'with null', 199 | params: [null], 200 | }, 201 | ]; 202 | 203 | goodCases.forEach((c, i) => { 204 | it(`works with (${c.label})`, async () => { 205 | const result = await client.getExchangeTxs(c.params[0]); 206 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 207 | }); 208 | }); 209 | badCases.forEach((c, i) => { 210 | it(`fails with (${c.label})`, async () => { 211 | await expect(client.getExchangeTxs(c.params[0])).rejects.toBeDefined(); 212 | }); 213 | }); 214 | }); 215 | 216 | describe('TransferTxs endpoint: ', async () => { 217 | type Case = { label: string; params: any[]; expectedUrl?: string }; 218 | const goodCases: Case[] = [ 219 | { 220 | label: 'single string', 221 | params: ['some id'], 222 | }, 223 | { 224 | label: 'empty call', 225 | params: [], 226 | }, 227 | { 228 | label: 'with one filter', 229 | params: [{ timeStart: '2016-01-01' }], 230 | }, 231 | { 232 | label: 'with all filters', 233 | params: [ 234 | { 235 | assetId: 'assetId', 236 | sender: 'sender', 237 | recipient: 'recipient', 238 | timeStart: '2016-02-01', 239 | timeEnd: '2016-03-01', 240 | limit: 5, 241 | sort: '-some', 242 | }, 243 | ], 244 | }, 245 | ]; 246 | const badCases: Case[] = [ 247 | { 248 | label: 'with wrong filters', 249 | params: [{ incorrectField: '' }], 250 | }, 251 | { 252 | label: 'with number', 253 | params: [1], 254 | }, 255 | { 256 | label: 'with null', 257 | params: [null], 258 | }, 259 | ]; 260 | 261 | goodCases.forEach((c, i) => { 262 | it(`works with (${c.label})`, async () => { 263 | const result = await client.getTransferTxs(c.params[0]); 264 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 265 | }); 266 | }); 267 | badCases.forEach((c, i) => { 268 | it(`fails with (${c.label})`, async () => { 269 | await expect(client.getTransferTxs(c.params[0])).rejects.toBeDefined(); 270 | }); 271 | }); 272 | }); 273 | 274 | describe('Pagination: ', () => { 275 | it('works', async () => { 276 | const customFetch = jest.fn(() => 277 | Promise.resolve( 278 | '{"__type": "list","lastCursor": "cursor", "data": [{ "data": 1 }]}' 279 | ) 280 | ); 281 | const customClient = new DataServiceClient({ 282 | rootUrl: NODE_URL, 283 | parse: parser, 284 | fetch: customFetch, 285 | }); 286 | 287 | const result = await customClient.getAssets('test'); 288 | expect(result).toHaveProperty('data'); 289 | expect(result).not.toHaveProperty('fetchMore'); 290 | 291 | const result2 = await customClient.getExchangeTxs({ 292 | sort: 'asc', 293 | limit: 1, 294 | }); 295 | expect(result2).toHaveProperty('data'); 296 | expect(result2).toHaveProperty('fetchMore'); 297 | const result3 = await result2.fetchMore(1); 298 | expect(result3).toHaveProperty('data'); 299 | expect(result3).toHaveProperty('fetchMore'); 300 | expect(customFetch.mock.calls.slice(-2)).toMatchSnapshot(); 301 | }); 302 | }); 303 | 304 | describe('Custom transformer: ', () => { 305 | const fetchMocks = { 306 | assets: JSON.stringify({ 307 | __type: 'list', 308 | data: [ 309 | { 310 | __type: 'asset', 311 | data: {}, 312 | }, 313 | { 314 | __type: 'asset', 315 | data: {}, 316 | }, 317 | ], 318 | }), 319 | pairs: JSON.stringify({ 320 | __type: 'list', 321 | data: [ 322 | { 323 | __type: 'pair', 324 | data: {}, 325 | }, 326 | { 327 | __type: 'pair', 328 | data: {}, 329 | }, 330 | ], 331 | }), 332 | candles: JSON.stringify({ 333 | __type: 'list', 334 | data: [ 335 | { 336 | __type: 'candle', 337 | data: {}, 338 | }, 339 | { 340 | __type: 'candle', 341 | data: {}, 342 | }, 343 | { 344 | __type: 'candle', 345 | data: {}, 346 | }, 347 | ], 348 | }), 349 | }; 350 | const customFetchMock = type => 351 | jest.fn(() => Promise.resolve(fetchMocks[type])); 352 | 353 | it('works for list of assets', async () => { 354 | const transformMocks = { 355 | list: jest.fn(d => d.map(customTransformer)), 356 | asset: jest.fn(), 357 | pair: jest.fn(), 358 | }; 359 | 360 | const customTransformer = ({ __type, data, ...etc }) => 361 | transformMocks[__type](data); 362 | 363 | const customClient = new DataServiceClient({ 364 | rootUrl: NODE_URL, 365 | parse: parser, 366 | fetch: customFetchMock('assets'), 367 | transform: customTransformer, 368 | }); 369 | const assets = await customClient.getAssets('1', '2'); 370 | expect(transformMocks.list).toHaveBeenCalledTimes(1); 371 | expect(transformMocks.asset).toHaveBeenCalledTimes(2); 372 | expect(transformMocks.pair).toHaveBeenCalledTimes(0); 373 | }); 374 | 375 | it('works for list of candles', async () => { 376 | const transformMocks = { 377 | list: jest.fn(d => d.map(customTransformer)), 378 | pair: jest.fn(), 379 | candle: jest.fn(), 380 | }; 381 | 382 | const customTransformer = ({ __type, data, ...etc }) => 383 | transformMocks[__type](data); 384 | 385 | const customClient = new DataServiceClient({ 386 | rootUrl: NODE_URL, 387 | parse: parser, 388 | fetch: customFetchMock('candles'), 389 | transform: customTransformer, 390 | }); 391 | 392 | const candles = await customClient.getCandles('WAVES', 'BTC', { 393 | timeStart: new Date(), 394 | interval: '1d', 395 | matcher: 'matcher', 396 | }); 397 | expect(transformMocks.list).toHaveBeenCalledTimes(1); 398 | expect(transformMocks.candle).toHaveBeenCalledTimes(3); 399 | expect(transformMocks.pair).toHaveBeenCalledTimes(0); 400 | }); 401 | }); 402 | 403 | describe('Long params transforms into POST request', () => { 404 | it('works', async () => { 405 | const ids = new Array(300) 406 | .fill(1) 407 | .map(() => 'AENTt5heWujAzcw7PmGXi1ekRc7CAmNm87Q1xZMYXGLa'); 408 | await client.getAssets(...ids); 409 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 410 | }); 411 | it('works for pairs', async () => { 412 | const pairs = new Array(300).fill(1).map( 413 | () => 414 | new AssetPair( 415 | new Asset({ id: 'WAVES' } as any), 416 | new Asset({ 417 | id: '8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS', 418 | } as any) 419 | ) 420 | ); 421 | await client.getPairs('3PJjwFREg8F9V6Cp9fnUuEwRts6HQQa5nfP')(pairs); 422 | expect(fetch.mock.calls.slice().pop()).toMatchSnapshot(); 423 | }); 424 | }); 425 | -------------------------------------------------------------------------------- /src/__tests__/utils.test.ts: -------------------------------------------------------------------------------- 1 | import { createQS, pipeP } from '../utils'; 2 | 3 | describe('Create querystring util', () => { 4 | it('works #1', () => { 5 | const obj = { a: true, b: 1, c: 'string', e: [9, 8, 7] }; 6 | const qs = createQS(obj); 7 | expect(qs).toBe('?a=true&b=1&c=string&e=9&e=8&e=7'); 8 | }); 9 | it('works with Date (custom serialization)', () => { 10 | const now = new Date(); 11 | const obj = { a: true, b: 1, c: 'string', d: now, e: [9, 8, 7] }; 12 | 13 | const qs = createQS(obj); 14 | expect(qs).toBe(`?a=true&b=1&c=string&d=${now.toISOString()}&e=9&e=8&e=7`); 15 | }); 16 | it('ignores undefined fields', () => { 17 | const obj = { a: true, b: 1, c: 'string', e: [9, 8, 7], d: undefined }; 18 | const qs = createQS(obj); 19 | expect(qs).toBe('?a=true&b=1&c=string&e=9&e=8&e=7'); 20 | }); 21 | }); 22 | 23 | describe('PipeP ', () => { 24 | const fn = pipeP( 25 | a => [a], 26 | b => [...b, 3] 27 | ); 28 | it('wraps 2 args in array', async () => { 29 | const result = await fn(1, 2); 30 | expect(result).toEqual([[1, 2], 3]); 31 | }); 32 | it("doesn't wrap 1 arg in array", async () => { 33 | const result = await fn(1); 34 | expect(result).toEqual([1, 3]); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /src/createRequest.ts: -------------------------------------------------------------------------------- 1 | import { createQS } from './utils'; 2 | import { HttpMethods, ILibRequest } from './types'; 3 | 4 | export const createRequest = (methodUrl: string, params?: any): ILibRequest => { 5 | const URL_MAX_LENGTH = 2000; 6 | if (typeof params === 'undefined') { 7 | return { url: methodUrl, method: HttpMethods.Get }; 8 | } 9 | const getUrl = `${methodUrl}${createQS(params)}`; 10 | return getUrl.length > URL_MAX_LENGTH 11 | ? { 12 | url: methodUrl, 13 | method: HttpMethods.Post, 14 | body: JSON.stringify(params), 15 | headers: { 16 | 'Content-Type': 'application/json', 17 | Accept: 'application/json, text/plain, */*', 18 | }, 19 | } 20 | : { url: getUrl, method: HttpMethods.Get }; 21 | }; 22 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { defaultFetch, defaultParse } from './utils'; 2 | import defaultTransform from './transform'; 3 | 4 | import createGetAssets from './methods/getAssets'; 5 | import createGetAssetsByTicker from './methods/getAssetsByTicker'; 6 | import createGetCandles from './methods/getCandles'; 7 | import createGetPairs from './methods/getPairs'; 8 | import createGetExchangeTxs from './methods/getExchangeTxs'; 9 | import createGetTransferTxs from './methods/getTransferTxs'; 10 | import createGetMassTransferTxs from './methods/getMassTransferTxs'; 11 | import createGetAliases from './methods/getAliases'; 12 | 13 | import { 14 | ILibOptions, 15 | IGetExchangeTxs, 16 | IGetTransferTxs, 17 | IGetMassTransferTxs, 18 | TAliases, 19 | TGetAssets, 20 | TGetAssetsByTicker, 21 | TGetCandles, 22 | TGetPairs, 23 | } from './types'; 24 | 25 | export default class DataServiceClient { 26 | public getPairs: TGetPairs; 27 | public getAssets: TGetAssets; 28 | public getAssetsByTicker: TGetAssetsByTicker; 29 | public getCandles: TGetCandles; 30 | public getExchangeTxs: IGetExchangeTxs; 31 | public getTransferTxs: IGetTransferTxs; 32 | public getMassTransferTxs: IGetMassTransferTxs; 33 | public aliases: TAliases; 34 | 35 | constructor(params: ILibOptions) { 36 | let options = { ...params }; 37 | if (!options.rootUrl) { 38 | throw new Error( 39 | 'No rootUrl was presented in options object. Check constructor call.' 40 | ); 41 | } 42 | // Add defaults 43 | if (!options.transform) { 44 | options.transform = defaultTransform; 45 | } 46 | if (!options.fetch) { 47 | options.fetch = defaultFetch; 48 | } 49 | if (!options.parse) { 50 | options.parse = defaultParse; 51 | } 52 | 53 | // Create methods 54 | this.getAssets = createGetAssets(options); 55 | this.getAssetsByTicker = createGetAssetsByTicker(options); 56 | this.getCandles = createGetCandles(options); 57 | this.getPairs = createGetPairs(options); 58 | this.getExchangeTxs = createGetExchangeTxs(options); 59 | this.getTransferTxs = createGetTransferTxs(options); 60 | this.getMassTransferTxs = createGetMassTransferTxs(options); 61 | this.aliases = createGetAliases(options); 62 | } 63 | } 64 | 65 | export * from './types'; 66 | export { defaultTransform }; 67 | -------------------------------------------------------------------------------- /src/methods/createMethod.ts: -------------------------------------------------------------------------------- 1 | import { T, pipeP } from '../utils'; 2 | import { TFunction, ILibOptions, ILibRequest, TResponse } from '../types'; 3 | 4 | type TCreateMethodParams = { 5 | validate: TFunction; 6 | generateRequest: TFunction>; 7 | libOptions: ILibOptions; 8 | addPaginationToArgs?: TFunction; 9 | }; 10 | 11 | const createMethod = ({ 12 | validate = T, 13 | generateRequest, 14 | libOptions, 15 | addPaginationToArgs, 16 | }: TCreateMethodParams): TFunction> => { 17 | function method(...args) { 18 | return pipeP( 19 | validate, 20 | generateRequest(libOptions.rootUrl), 21 | ({ url, ...options }) => libOptions.fetch(url, options), 22 | libOptions.parse, 23 | rawData => 24 | pipeP( 25 | libOptions.transform, 26 | addPagination({ method, args, addPaginationToArgs, rawData }) 27 | )(rawData) 28 | )(...args); 29 | } 30 | return method; 31 | }; 32 | 33 | const addPagination = ({ 34 | method, 35 | args, 36 | addPaginationToArgs, 37 | rawData, 38 | }) => data => { 39 | if (!data || !addPaginationToArgs || !rawData || !rawData.lastCursor) { 40 | return { data }; 41 | } 42 | return { 43 | data, 44 | fetchMore: count => 45 | method(addPaginationToArgs({ args, cursor: rawData.lastCursor, count })), 46 | }; 47 | }; 48 | 49 | export { createMethod }; 50 | -------------------------------------------------------------------------------- /src/methods/getAliases.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ILibOptions, 3 | ILibRequest, 4 | TCreateGetFn, 5 | TAliasesByAddressParams, 6 | TAliasId, 7 | TAlias, 8 | TAliases, 9 | } from '../types'; 10 | 11 | import { isNotString } from '../utils'; 12 | import { createMethod } from './createMethod'; 13 | import { createRequest } from '../createRequest'; 14 | 15 | const validateId = (id: string): Promise => 16 | isNotString(id) 17 | ? Promise.reject(new Error('ArgumentsError: aliasId should be string')) 18 | : Promise.resolve(id); 19 | 20 | const validateIdList = (idList: Array): Promise> => 21 | Array.isArray(idList) 22 | ? Promise.resolve(idList) 23 | : Promise.reject(new Error('ArgumentsError: aliasId should be Array')); 24 | 25 | const validateByAddressParams = ([ 26 | address, 27 | options, 28 | ]: TAliasesByAddressParams): Promise => 29 | isNotString(address) 30 | ? Promise.reject(new Error('ArgumentsError: address should be string')) 31 | : Promise.resolve([address, options] as TAliasesByAddressParams); 32 | 33 | const createRequestForId = (rootUrl: string) => (id: TAliasId): ILibRequest => 34 | createRequest(`${rootUrl}/aliases/${id}`); 35 | 36 | const createRequestForIdList = (rootUrl: string) => (idList: Array): ILibRequest => 37 | createRequest(`${rootUrl}/aliases/?aliases=${idList.join(',')}`); 38 | 39 | const createRequestForAddress = (rootUrl: string) => ([ 40 | address, 41 | { showBroken }, 42 | ]: TAliasesByAddressParams): ILibRequest => 43 | createRequest(`${rootUrl}/aliases`, { 44 | address, 45 | showBroken, 46 | }); 47 | 48 | const createGetAliases: TCreateGetFn = (libOptions: ILibOptions) => ({ 49 | getById: createMethod({ 50 | validate: validateId, 51 | generateRequest: createRequestForId, 52 | libOptions, 53 | }), 54 | getByIdList: createMethod({ 55 | validate: validateIdList, 56 | generateRequest: createRequestForIdList, 57 | libOptions, 58 | }), 59 | getByAddress: (address, options = {}) => 60 | createMethod({ 61 | validate: validateByAddressParams, 62 | generateRequest: createRequestForAddress, 63 | libOptions, 64 | })(address, options), 65 | }); 66 | 67 | export default createGetAliases; 68 | -------------------------------------------------------------------------------- /src/methods/getAssets.ts: -------------------------------------------------------------------------------- 1 | import { Asset } from '@waves/data-entities'; 2 | import { 3 | ILibOptions, 4 | ILibRequest, 5 | TAssetId, 6 | TGetAssets, 7 | TCreateGetFn, 8 | } from '../types'; 9 | 10 | import { isNotString } from '../utils'; 11 | import { createMethod } from './createMethod'; 12 | import { createRequest } from '../createRequest'; 13 | 14 | const validateIds = (idOrIds: TAssetId[] | TAssetId): Promise => { 15 | const arrayToCheck = Array.isArray(idOrIds) ? idOrIds : [idOrIds]; 16 | return arrayToCheck.some(isNotString) 17 | ? Promise.reject(new Error('ArgumentsError: AssetId should be string')) 18 | : Promise.resolve(arrayToCheck); 19 | }; 20 | 21 | const createRequestForMany = (rootUrl: string) => ( 22 | ids: TAssetId[] 23 | ): ILibRequest => createRequest(`${rootUrl}/assets`, { ids }); 24 | 25 | const createGetAssets: TCreateGetFn = (libOptions: ILibOptions) => 26 | createMethod({ 27 | validate: validateIds, 28 | generateRequest: createRequestForMany, 29 | libOptions, 30 | }); 31 | 32 | export default createGetAssets; 33 | -------------------------------------------------------------------------------- /src/methods/getAssetsByTicker.ts: -------------------------------------------------------------------------------- 1 | import { Asset } from '@waves/data-entities'; 2 | import { 3 | TCreateGetFn, 4 | ILibOptions, 5 | ILibRequest, 6 | TGetAssetsByTicker, 7 | } from '../types'; 8 | 9 | import { createMethod } from './createMethod'; 10 | import { createRequest } from '../createRequest'; 11 | 12 | const validateTicker = (ticker: string): Promise => { 13 | return typeof ticker !== 'string' 14 | ? Promise.reject(new Error('ArgumentsError: Ticker should be string')) 15 | : Promise.resolve(ticker); 16 | }; 17 | 18 | const createRequestForMany = (rootUrl: string) => ( 19 | ticker: string 20 | ): ILibRequest => createRequest(`${rootUrl}/assets`, { ticker }); 21 | 22 | const createGetAssetsByTicker: TCreateGetFn = ( 23 | libOptions: ILibOptions 24 | ) => 25 | createMethod({ 26 | validate: validateTicker, 27 | generateRequest: createRequestForMany, 28 | libOptions, 29 | }); 30 | 31 | export default createGetAssetsByTicker; 32 | -------------------------------------------------------------------------------- /src/methods/getCandles.ts: -------------------------------------------------------------------------------- 1 | import { Candle } from '@waves/data-entities'; 2 | import { 3 | ILibOptions, 4 | ILibRequest, 5 | TCreateGetFn, 6 | TCandlesParams, 7 | TCandlesRequestFilters, 8 | TGetCandles, 9 | } from '../types'; 10 | 11 | import { createMethod } from './createMethod'; 12 | import { createRequest } from '../createRequest'; 13 | 14 | type TCandlesParamsKey = keyof TCandlesParams; 15 | 16 | const possibleParams: Array = [ 17 | 'timeStart', 18 | 'timeEnd', 19 | 'interval', 20 | 'matcher', 21 | ]; 22 | 23 | const isCandlesParams = (params: any): params is TCandlesParams => 24 | typeof params === 'object' && 25 | Object.keys(params).every((k: TCandlesParamsKey) => 26 | possibleParams.includes(k) 27 | ); 28 | 29 | const isFilters = (filters: any): filters is TCandlesRequestFilters => 30 | Array.isArray(filters) && 31 | filters.length === 3 && 32 | typeof filters[0] === 'string' && 33 | typeof filters[1] === 'string' && 34 | isCandlesParams(filters[2]); 35 | 36 | const validateFilters = (filters: any) => 37 | isFilters(filters) 38 | ? Promise.resolve(filters) 39 | : Promise.reject('Wrong filters object'); 40 | 41 | const createRequestForCandles = (rootUrl: string) => ([ 42 | amountAssetId, 43 | priceAssetId, 44 | params, 45 | ]: TCandlesRequestFilters): ILibRequest => 46 | createRequest(`${rootUrl}/candles/${amountAssetId}/${priceAssetId}`, params); 47 | 48 | const createGetCandles: TCreateGetFn = (libOptions: ILibOptions) => 49 | createMethod({ 50 | validate: validateFilters, 51 | generateRequest: createRequestForCandles, 52 | libOptions, 53 | }); 54 | 55 | export default createGetCandles; 56 | -------------------------------------------------------------------------------- /src/methods/getExchangeTxs.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ILibRequest, 3 | TCreateGetFn, 4 | ITransaction, 5 | IExchangeTxFilters, 6 | IGetExchangeTxs, 7 | } from '../types'; 8 | 9 | import { createMethod } from './createMethod'; 10 | import { createRequest } from '../createRequest'; 11 | 12 | // One 13 | const validateId = id => 14 | typeof id === 'string' ? Promise.resolve(id) : Promise.reject('Wrong id'); 15 | const generateRequestOne = (rootUrl: string) => (id: string): ILibRequest => 16 | createRequest(`${rootUrl}/transactions/exchange/${id}`); 17 | 18 | //Many 19 | const isFilters = (filters: any): filters is IExchangeTxFilters => { 20 | const possibleFilters = [ 21 | 'timeStart', 22 | 'timeEnd', 23 | 'limit', 24 | 'sort', 25 | 'matcher', 26 | 'sender', 27 | 'amountAsset', 28 | 'priceAsset', 29 | 'after', 30 | ]; 31 | return ( 32 | typeof filters === 'object' && 33 | Object.keys(filters).every(k => possibleFilters.includes(k)) 34 | ); 35 | }; 36 | const validateFilters = (filters: any) => 37 | isFilters(filters) 38 | ? Promise.resolve(filters) 39 | : Promise.reject('Wrong filters object'); 40 | 41 | const generateRequestMany = (rootUrl: string) => ( 42 | filters: IExchangeTxFilters 43 | ): ILibRequest => createRequest(`${rootUrl}/transactions/exchange`, filters); 44 | 45 | const createGetExchangeTxs: TCreateGetFn = libOptions => { 46 | const getExchangeTxsOne = createMethod({ 47 | validate: validateId, 48 | generateRequest: generateRequestOne, 49 | libOptions, 50 | }); 51 | const getExchangeTxsMany = createMethod({ 52 | validate: validateFilters, 53 | generateRequest: generateRequestMany, 54 | libOptions, 55 | addPaginationToArgs: ({ args: [filters], cursor, count }) => ({ 56 | ...filters, 57 | after: cursor, 58 | ...(count ? { limit: count } : {}), 59 | }), 60 | }); 61 | 62 | const getExchangeTxs: IGetExchangeTxs = ( 63 | idOrFilters: string | IExchangeTxFilters = {} 64 | ) => 65 | typeof idOrFilters === 'string' 66 | ? getExchangeTxsOne(idOrFilters) 67 | : getExchangeTxsMany(idOrFilters); 68 | 69 | return getExchangeTxs; 70 | }; 71 | 72 | export default createGetExchangeTxs; 73 | -------------------------------------------------------------------------------- /src/methods/getMassTransferTxs.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ILibRequest, 3 | TCreateGetFn, 4 | ITransaction, 5 | IMassTransferTxFilters, 6 | IGetMassTransferTxs, 7 | } from '../types'; 8 | 9 | import { createMethod } from './createMethod'; 10 | import { createRequest } from '../createRequest'; 11 | 12 | // One 13 | const validateId = id => 14 | typeof id === 'string' ? Promise.resolve(id) : Promise.reject('Wrong id'); 15 | const generateRequestOne = (rootUrl: string) => (id: string): ILibRequest => 16 | createRequest(`${rootUrl}/transactions/mass-transfer/${id}`); 17 | 18 | //Many 19 | const isFilters = (filters: any): filters is IMassTransferTxFilters => { 20 | const possibleFilters = [ 21 | 'sender', 22 | 'assetId', 23 | 'recipient', 24 | 'after', 25 | 'timeStart', 26 | 'timeEnd', 27 | 'sort', 28 | 'limit', 29 | ]; 30 | return ( 31 | typeof filters === 'object' && 32 | Object.keys(filters).every(k => possibleFilters.includes(k)) 33 | ); 34 | }; 35 | const validateFilters = (filters: any) => 36 | isFilters(filters) 37 | ? Promise.resolve(filters) 38 | : Promise.reject('Wrong filters object'); 39 | 40 | const generateRequestMany = (rootUrl: string) => ( 41 | filters: IMassTransferTxFilters 42 | ): ILibRequest => 43 | createRequest(`${rootUrl}/transactions/mass-transfer`, filters); 44 | 45 | const createGetMassTransferTxs: TCreateGetFn< 46 | IGetMassTransferTxs 47 | > = libOptions => { 48 | const getMassTransferTxsOne = createMethod({ 49 | validate: validateId, 50 | generateRequest: generateRequestOne, 51 | libOptions, 52 | }); 53 | const getMassTransferTxsMany = createMethod({ 54 | validate: validateFilters, 55 | generateRequest: generateRequestMany, 56 | libOptions, 57 | addPaginationToArgs: ({ args: [filters], cursor, count }) => ({ 58 | ...filters, 59 | after: cursor, 60 | ...(count ? { limit: count } : {}), 61 | }), 62 | }); 63 | 64 | const getMassTransferTxs: IGetMassTransferTxs = ( 65 | idOrFilters: string | IMassTransferTxFilters = {} 66 | ) => 67 | typeof idOrFilters === 'string' 68 | ? getMassTransferTxsOne(idOrFilters) 69 | : getMassTransferTxsMany(idOrFilters); 70 | 71 | return getMassTransferTxs; 72 | }; 73 | 74 | export default createGetMassTransferTxs; 75 | -------------------------------------------------------------------------------- /src/methods/getPairs.ts: -------------------------------------------------------------------------------- 1 | import { 2 | TCreateGetFn, 3 | ILibOptions, 4 | ILibRequest, 5 | TGetPairs, 6 | TPairsRequest, 7 | TPairJSON, 8 | } from '../types'; 9 | import { AssetPair } from '@waves/data-entities'; 10 | import { createMethod } from './createMethod'; 11 | import { createRequest } from '../createRequest'; 12 | 13 | const isAssetPair = pair => { 14 | switch (true) { 15 | case typeof pair === 'string': 16 | return pair.split('/').length === 2; 17 | case typeof pair === 'object': 18 | return AssetPair.isAssetPair(pair); 19 | default: 20 | return false; 21 | } 22 | }; 23 | 24 | const isValidPairsFilters = (request: any): request is TPairsRequest => { 25 | return ( 26 | Array.isArray(request) && 27 | request.length === 2 && 28 | typeof request[0] === 'string' && 29 | (Array.isArray(request[1]) ? request[1] : [request[1]]).every(isAssetPair) 30 | ); 31 | }; 32 | 33 | const validateRequest = (matcher: any) => ( 34 | pairs: any 35 | ): Promise => { 36 | const request = [matcher, pairs]; 37 | return isValidPairsFilters(request) 38 | ? Promise.resolve(request) 39 | : Promise.reject( 40 | new Error( 41 | 'ArgumentsError: AssetPair should be object with amountAsset, priceAsset' 42 | ) 43 | ); 44 | }; 45 | 46 | const createRequestForMany = (nodeUrl: string) => ([ 47 | matcher, 48 | pairs, 49 | ]: TPairsRequest): ILibRequest => 50 | createRequest(`${nodeUrl}/pairs`, { 51 | pairs: pairs.map(p => p.toString()), 52 | matcher, 53 | }); 54 | 55 | const getPairs: TCreateGetFn = (libOptions: ILibOptions) => ( 56 | matcher: string 57 | ) => 58 | createMethod({ 59 | validate: validateRequest(matcher), 60 | generateRequest: createRequestForMany, 61 | libOptions, 62 | }); 63 | 64 | export default getPairs; 65 | -------------------------------------------------------------------------------- /src/methods/getTransferTxs.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ILibRequest, 3 | TCreateGetFn, 4 | TResponse, 5 | ITransaction, 6 | ITransferTxFilters, 7 | IGetTransferTxs, 8 | } from '../types'; 9 | 10 | import { createMethod } from './createMethod'; 11 | import { createRequest } from '../createRequest'; 12 | 13 | // One 14 | const validateId = id => 15 | typeof id === 'string' ? Promise.resolve(id) : Promise.reject('Wrong id'); 16 | const generateRequestOne = (rootUrl: string) => (id: string): ILibRequest => 17 | createRequest(`${rootUrl}/transactions/transfer/${id}`); 18 | 19 | //Many 20 | const isFilters = (filters: any): filters is ITransferTxFilters => { 21 | const possibleFilters = [ 22 | 'sender', 23 | 'assetId', 24 | 'recipient', 25 | 'after', 26 | 'timeStart', 27 | 'timeEnd', 28 | 'sort', 29 | 'limit', 30 | ]; 31 | return ( 32 | typeof filters === 'object' && 33 | Object.keys(filters).every(k => possibleFilters.includes(k)) 34 | ); 35 | }; 36 | const validateFilters = (filters: any) => 37 | isFilters(filters) 38 | ? Promise.resolve(filters) 39 | : Promise.reject('Wrong filters object'); 40 | 41 | const generateRequestMany = (rootUrl: string) => ( 42 | filters: ITransferTxFilters 43 | ): ILibRequest => createRequest(`${rootUrl}/transactions/transfer`, filters); 44 | 45 | const createGetTransferTxs: TCreateGetFn = libOptions => { 46 | const getTransferTxsOne = createMethod({ 47 | validate: validateId, 48 | generateRequest: generateRequestOne, 49 | libOptions, 50 | }); 51 | const getTransferTxsMany = createMethod({ 52 | validate: validateFilters, 53 | generateRequest: generateRequestMany, 54 | libOptions, 55 | addPaginationToArgs: ({ args: [filters], cursor, count }) => ({ 56 | ...filters, 57 | after: cursor, 58 | ...(count ? { limit: count } : {}), 59 | }), 60 | }); 61 | 62 | const getTransferTxs: IGetTransferTxs = ( 63 | idOrFilters: string | ITransferTxFilters = {} 64 | ) => 65 | typeof idOrFilters === 'string' 66 | ? getTransferTxsOne(idOrFilters) 67 | : getTransferTxsMany(idOrFilters); 68 | 69 | return getTransferTxs; 70 | }; 71 | 72 | export default createGetTransferTxs; 73 | -------------------------------------------------------------------------------- /src/transform.ts: -------------------------------------------------------------------------------- 1 | import { Asset, IAssetJSON, Candle, ICandleJSON } from '@waves/data-entities'; 2 | import { ApiTypes } from './types'; 3 | import { id } from './utils'; 4 | const transformer = ({ __type, data, ...rest }) => { 5 | switch (__type) { 6 | case ApiTypes.List: 7 | return data.map(transformer); 8 | case ApiTypes.Asset: 9 | return transformAsset(data); 10 | case ApiTypes.Alias: 11 | return data; 12 | case ApiTypes.Pair: 13 | return transformPair(data); 14 | case ApiTypes.Transaction: 15 | return data; 16 | case ApiTypes.Candle: 17 | return transformCandle(data); 18 | default: 19 | return { __type, data, ...rest }; 20 | } 21 | }; 22 | 23 | const transformAsset = (data: IAssetJSON): Asset => 24 | data === null ? null : new Asset(data); 25 | const transformPair = id; 26 | const transformCandle = (data: ICandleJSON): Candle => 27 | data === null ? null : new Candle(data); 28 | 29 | export default transformer; 30 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import { Asset, Candle, AssetPair } from '@waves/data-entities'; 2 | import { BigNumber } from '@waves/bignumber'; 3 | 4 | export enum ApiTypes { 5 | List = 'list', 6 | Asset = 'asset', 7 | Pair = 'pair', 8 | Transaction = 'transaction', 9 | Alias = 'alias', 10 | Candle = 'candle', 11 | } 12 | export enum HttpMethods { 13 | Get = 'GET', 14 | Post = 'POST', 15 | } 16 | export interface ILibRequest { 17 | url: string; 18 | method: HttpMethods; 19 | headers?: {}; 20 | body?: {}; 21 | } 22 | export interface ILibOptions { 23 | rootUrl: string; 24 | parse?: TParser; 25 | fetch?: TFunction; 26 | transform?: TFunction; 27 | } 28 | 29 | export type TListResponseJSON = { 30 | __type: ApiTypes.List; 31 | data: T[]; 32 | }; 33 | export type TResponse = Promise<{ 34 | data: T; 35 | fetchMore?: TFunction>; 36 | }>; 37 | export type TCreateGetFn = (libOptions: ILibOptions) => T; 38 | export type TPredicate = (...args: any[]) => boolean; 39 | export type TFunction = (...args: any[]) => T; 40 | export type TParser = (text: string) => any; 41 | 42 | export interface ITransaction { 43 | // @TODO add txs interfaces 44 | } 45 | export interface IExchangeTxFilters { 46 | timeStart?: string | Date | number; 47 | timeEnd?: string | Date | number; 48 | matcher?: string; 49 | sender?: string; 50 | amountAsset?: string | Asset; 51 | priceAsset?: string | Asset; 52 | limit?: number; 53 | sort?: string; 54 | } 55 | export interface ITransferTxFilters { 56 | sender?: string; 57 | recipient?: string; 58 | assetId?: string; 59 | timeStart?: string | Date | number; 60 | timeEnd?: string | Date | number; 61 | limit?: number; 62 | sort?: string; 63 | } 64 | 65 | export interface IMassTransferTxFilters { 66 | sender?: string; 67 | recipient?: string; 68 | assetId?: string; 69 | timeStart?: string | Date | number; 70 | timeEnd?: string | Date | number; 71 | limit?: number; 72 | sort?: string; 73 | } 74 | 75 | export interface IGetExchangeTxs { 76 | (filters: IExchangeTxFilters): TResponse; 77 | (id: string): TResponse; 78 | (): TResponse; 79 | } 80 | export interface IGetTransferTxs { 81 | (filters: ITransferTxFilters): TResponse; 82 | (id: string): TResponse; 83 | (): TResponse; 84 | } 85 | export interface IGetMassTransferTxs { 86 | (filters: IMassTransferTxFilters): TResponse; 87 | (id: string): TResponse; 88 | (): TResponse; 89 | } 90 | 91 | export type TAssetId = string; 92 | export type TGetAssets = (...ids: TAssetId[]) => TResponse; 93 | export type TGetAssetsByTicker = (ticker: string) => TResponse; 94 | 95 | export type TAliasId = string; 96 | export type TAlias = { 97 | address: string; 98 | alias: string; 99 | }; 100 | export type TAliasesByAddressOptions = { showBroken?: boolean }; 101 | export type TAliasesByAddressParams = [string, TAliasesByAddressOptions]; 102 | export type TAliases = { 103 | getById: TGetAliasById; 104 | getByIdList: TGetAliasByIdList; 105 | getByAddress: TGetAliasesByAddress; 106 | }; 107 | export type TGetAliasById = (id: TAliasId) => TResponse; 108 | export type TGetAliasByIdList = (idList: Array) => TResponse; 109 | export type TGetAliasesByAddress = ( 110 | address: string, 111 | options?: TAliasesByAddressOptions 112 | ) => TResponse; 113 | 114 | export type TCandlesParams = { 115 | timeStart: string | Date | number; 116 | timeEnd?: string | Date | number; 117 | interval: string; 118 | matcher: string; 119 | }; 120 | export type TCandlesRequestFilters = [string, string, TCandlesParams]; 121 | export type TGetCandles = ( 122 | amountAsset: string, 123 | priceAsset: string, 124 | params: TCandlesParams 125 | ) => TResponse; 126 | 127 | export type TPairsRequest = [string, AssetPair[]]; 128 | export type TPairJSON = { 129 | firstPrice: BigNumber; 130 | lastPrice: BigNumber; 131 | volume: BigNumber; 132 | amountAsset: string; 133 | priceAsset: string; 134 | }; 135 | export type TGetPairs = ( 136 | matcher: string 137 | ) => (pairs: AssetPair[]) => TResponse; 138 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { TPredicate, TFunction } from './types'; 2 | 3 | export const noop = () => {}; 4 | export const defaultFetch = (...args): Promise => { 5 | return (window as any) 6 | .fetch(...args) 7 | .then((res: Response) => 8 | res.ok 9 | ? res.text() 10 | : res.text().then(str => Promise.reject(new Error(str))) 11 | ); 12 | }; 13 | export const defaultParse = JSON.parse.bind(JSON); 14 | export const isNotString = (value: any): boolean => typeof value !== 'string'; 15 | export const pipeP = (...fns: TFunction[]) => ( 16 | ...args: any[] 17 | ): Promise => 18 | fns.reduce( 19 | (prev, fn) => prev.then(fn), 20 | Promise.resolve(args.length === 1 ? args[0] : args) 21 | ); 22 | export const some = (predicate: TPredicate) => (arr: any[]): boolean => 23 | arr.some(predicate); 24 | 25 | /** 26 | * @param obj flat object with primitives or arrays of primitives as values 27 | * @returns query string for obj 28 | */ 29 | /** 30 | * customSerialize :: a -> string 31 | */ 32 | const customSerialize = v => { 33 | switch (true) { 34 | case v instanceof Date: 35 | return v.toISOString(); 36 | default: 37 | return v; 38 | } 39 | }; 40 | const createKeyValue = (key, v) => `${key}=${customSerialize(v)}`; 41 | export const createQS = (obj: Object): string => { 42 | const qs = Object.entries(obj) 43 | .filter(([_, value]) => value !== undefined) 44 | .map(([key, valueOrValues]) => { 45 | return Array.isArray(valueOrValues) 46 | ? valueOrValues.map(v => createKeyValue(key, v)).join('&') 47 | : createKeyValue(key, valueOrValues); 48 | }) 49 | .join('&'); 50 | return qs === '' ? qs : `?${qs}`; 51 | }; 52 | 53 | export const id = _ => _; 54 | export const T = (...args) => true; 55 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "outDir": "dist/", 7 | "moduleResolution": "node", 8 | "lib": [ 9 | "es2017", 10 | "es2015.promise", 11 | "dom" 12 | ] 13 | }, 14 | "exclude": [ 15 | "*.sandbox.js", 16 | "*.sandbox.ts", 17 | "**/__tests__/**" 18 | ], 19 | "include": [ 20 | "src/index.ts" 21 | ] 22 | } 23 | --------------------------------------------------------------------------------