├── docs ├── .nojekyll ├── modules.md ├── _sidebar.md ├── enums │ ├── constants.network.md │ └── constants.ilostate.md ├── index.html ├── interfaces │ └── batch.batchrequest.md ├── modules │ ├── batch.md │ ├── constants.md │ ├── utils.md │ ├── zilo.md │ └── index.md ├── CONTRIBUTING.md ├── README.md └── classes │ ├── zilo.zilo-1.md │ └── index.zilswap.md ├── .gitignore ├── .prettierrc ├── tslint.json ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── LICENSE ├── package.json ├── src ├── batch.ts ├── constants.ts ├── utils.ts ├── test.ts ├── zilo.ts └── index.ts ├── README.md ├── CODE_OF_CONDUCT.md ├── tsconfig.json └── yarn.lock /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /lib 3 | index.js 4 | .DS_Store 5 | yarn-error.log 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 140, 3 | "singleQuote": true, 4 | "semi": false, 5 | "arrowParens": "avoid" 6 | } 7 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint:recommended", "tslint-config-prettier"], 3 | "rules": { 4 | "one-variable-per-declaration": false, 5 | "no-console": false, 6 | "no-string-literal": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/modules.md: -------------------------------------------------------------------------------- 1 | [zilswap-sdk](README.md) / Exports 2 | 3 | # zilswap-sdk 4 | 5 | ## Table of contents 6 | 7 | ### Modules 8 | 9 | - [batch](modules/batch.md) 10 | - [constants](modules/constants.md) 11 | - [index](modules/index.md) 12 | - [utils](modules/utils.md) 13 | - [zilo](modules/zilo.md) 14 | -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | - [Documentation](/) 2 | - [modules] 3 | - [batch](modules/batch.md) 4 | - [constants](modules/constants.md) 5 | - [utils](modules/utils.md) 6 | - [zilo](modules/zilo.md) 7 | - [zilswap](modules/index.md) 8 | - classes 9 | - [zilo](classes/zilo.zilo-1.md) 10 | - [zilswap](classes/index.zilswap.md) 11 | - enums 12 | - [ilostate](enums/constants.ilostate.md) 13 | - [network](enums/constants.network.md) 14 | - interfaces 15 | - [batchrequest](interfaces/batch.batchrequest.md) 16 | - [Contributing](CONTRIBUTING.md) 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE] ..." 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /docs/enums/constants.network.md: -------------------------------------------------------------------------------- 1 | [zilswap-sdk](../README.md) / [Exports](../modules.md) / [constants](../modules/constants.md) / Network 2 | 3 | # Enumeration: Network 4 | 5 | [constants](../modules/constants.md) 6 | 7 | ## Table of contents 8 | 9 | ### Enumeration members 10 | 11 | - [MainNet](constants.network.md#mainnet) 12 | - [TestNet](constants.network.md#testnet) 13 | 14 | ## Enumeration members 15 | 16 | ### MainNet 17 | 18 | • **MainNet** = "MainNet" 19 | 20 | #### Defined in 21 | 22 | [constants.ts:4](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L4) 23 | 24 | ___ 25 | 26 | ### TestNet 27 | 28 | • **TestNet** = "TestNet" 29 | 30 | #### Defined in 31 | 32 | [constants.ts:5](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L5) 33 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Document 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG] ..." 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Switcheo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/interfaces/batch.batchrequest.md: -------------------------------------------------------------------------------- 1 | [zilswap-sdk](../README.md) / [Exports](../modules.md) / [batch](../modules/batch.md) / BatchRequest 2 | 3 | # Interface: BatchRequest 4 | 5 | [batch](../modules/batch.md) 6 | 7 | ## Table of contents 8 | 9 | ### Properties 10 | 11 | - [id](batch.batchrequest.md#id) 12 | - [jsonrpc](batch.batchrequest.md#jsonrpc) 13 | - [method](batch.batchrequest.md#method) 14 | - [params](batch.batchrequest.md#params) 15 | 16 | ## Properties 17 | 18 | ### id 19 | 20 | • **id**: `string` 21 | 22 | #### Defined in 23 | 24 | [batch.ts:4](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/batch.ts#L4) 25 | 26 | ___ 27 | 28 | ### jsonrpc 29 | 30 | • **jsonrpc**: `string` 31 | 32 | #### Defined in 33 | 34 | [batch.ts:5](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/batch.ts#L5) 35 | 36 | ___ 37 | 38 | ### method 39 | 40 | • **method**: `string` 41 | 42 | #### Defined in 43 | 44 | [batch.ts:6](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/batch.ts#L6) 45 | 46 | ___ 47 | 48 | ### params 49 | 50 | • **params**: `any`[] 51 | 52 | #### Defined in 53 | 54 | [batch.ts:7](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/batch.ts#L7) 55 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zilswap-sdk", 3 | "version": "1.3.27", 4 | "description": "Zilswap TypeScript SDK", 5 | "main": "lib/index.js", 6 | "types": "lib/index.d.ts", 7 | "repository": "https://github.com/Switcheo/zilswap-sdk", 8 | "homepage": "https://github.com/Switcheo/zilswap-sdk#readme", 9 | "author": "Switcheo ", 10 | "license": "MIT", 11 | "scripts": { 12 | "build": "tsc", 13 | "test": "tsc && node lib/test.js", 14 | "format": "prettier --write \"src/**/*.ts\"", 15 | "lint": "tslint -p tsconfig.json", 16 | "prepare": "yarn run build", 17 | "prepublishOnly": "yarn run lint", 18 | "preversion": "yarn run lint", 19 | "version": "yarn run format && git add -A src", 20 | "postversion": "git push && git push --tags" 21 | }, 22 | "files": [ 23 | "lib/**/*" 24 | ], 25 | "dependencies": { 26 | "@zilliqa-js/zilliqa": "^2.2.0", 27 | "async-mutex": "^0.2.2", 28 | "bignumber.js": "^9.0.0", 29 | "bn.js": "^5.1.1", 30 | "isomorphic-fetch": "^3.0.0", 31 | "tslib": "^1.11.2" 32 | }, 33 | "devDependencies": { 34 | "@types/node": "^13.13.5", 35 | "@types/websocket": "^1.0.0", 36 | "prettier": "^2.0.5", 37 | "tslint-config-prettier": "^1.18.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/batch.ts: -------------------------------------------------------------------------------- 1 | import 'isomorphic-fetch' 2 | 3 | export interface BatchRequest { 4 | id: string 5 | jsonrpc: string 6 | method: string 7 | params: any[] 8 | } 9 | 10 | export type BatchResponse = { [key in string]: any } 11 | 12 | /** 13 | * Sends a series of requests as a batch to the Zilliqa API. 14 | * 15 | * @param rpcEndpoint The rpc endpoint to query. 16 | * @param requests[] An array of RPC requests. 17 | * @returns Promise<{ [key in string]: BatchResponse }> Map of RPC responses keyed by the request ID. 18 | */ 19 | export const sendBatchRequest = async (rpcEndpoint: string, requests: BatchRequest[]): Promise => { 20 | const response = await fetch(rpcEndpoint, { 21 | method: 'POST', 22 | mode: 'cors', 23 | cache: 'no-cache', 24 | headers: { 25 | 'Content-Type': 'application/json', 26 | }, 27 | redirect: 'follow', 28 | referrerPolicy: 'no-referrer', 29 | body: JSON.stringify(requests), 30 | }) 31 | 32 | const results: BatchResponse[] = await response.json() 33 | const errors = results 34 | .map(r => (r.error ? `[${r.id}] ${r.error.message}` : null)) 35 | .filter(e => !!e) 36 | .join('. ') 37 | if (errors && errors.length > 0) { 38 | throw new Error('Failed to send batch request: ' + errors) 39 | } 40 | return results.reduce((a, c) => ({ ...a, [c.id]: c.result }), {}) 41 | } 42 | -------------------------------------------------------------------------------- /docs/modules/batch.md: -------------------------------------------------------------------------------- 1 | [zilswap-sdk](../README.md) / [Exports](../modules.md) / batch 2 | 3 | # Module: batch 4 | 5 | ## Table of contents 6 | 7 | ### Interfaces 8 | 9 | - [BatchRequest](../interfaces/batch.batchrequest.md) 10 | 11 | ### Type aliases 12 | 13 | - [BatchResponse](batch.md#batchresponse) 14 | 15 | ### Functions 16 | 17 | - [sendBatchRequest](batch.md#sendbatchrequest) 18 | 19 | ## Type aliases 20 | 21 | ### BatchResponse 22 | 23 | Ƭ **BatchResponse**: { [key in string]: any} 24 | 25 | #### Defined in 26 | 27 | [batch.ts:10](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/batch.ts#L10) 28 | 29 | ## Functions 30 | 31 | ### sendBatchRequest 32 | 33 | ▸ `Const` **sendBatchRequest**(`rpcEndpoint`, `requests`): `Promise`<[BatchResponse](batch.md#batchresponse)\> 34 | 35 | Sends a series of requests as a batch to the Zilliqa API. 36 | 37 | #### Parameters 38 | 39 | | Name | Type | Description | 40 | | :------ | :------ | :------ | 41 | | `rpcEndpoint` | `string` | The rpc endpoint to query. | 42 | | `requests` | [BatchRequest](../interfaces/batch.batchrequest.md)[] | - | 43 | 44 | #### Returns 45 | 46 | `Promise`<[BatchResponse](batch.md#batchresponse)\> 47 | 48 | Promise<{ [key in string]: BatchResponse }> Map of RPC responses keyed by the request ID. 49 | 50 | #### Defined in 51 | 52 | [batch.ts:19](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/batch.ts#L19) 53 | -------------------------------------------------------------------------------- /docs/enums/constants.ilostate.md: -------------------------------------------------------------------------------- 1 | [zilswap-sdk](../README.md) / [Exports](../modules.md) / [constants](../modules/constants.md) / ILOState 2 | 3 | # Enumeration: ILOState 4 | 5 | [constants](../modules/constants.md) 6 | 7 | ## Table of contents 8 | 9 | ### Enumeration members 10 | 11 | - [Active](constants.ilostate.md#active) 12 | - [Completed](constants.ilostate.md#completed) 13 | - [Failed](constants.ilostate.md#failed) 14 | - [Pending](constants.ilostate.md#pending) 15 | - [Uninitialized](constants.ilostate.md#uninitialized) 16 | 17 | ## Enumeration members 18 | 19 | ### Active 20 | 21 | • **Active** = "Active" 22 | 23 | #### Defined in 24 | 25 | [constants.ts:27](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L27) 26 | 27 | ___ 28 | 29 | ### Completed 30 | 31 | • **Completed** = "Completed" 32 | 33 | #### Defined in 34 | 35 | [constants.ts:29](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L29) 36 | 37 | ___ 38 | 39 | ### Failed 40 | 41 | • **Failed** = "Failed" 42 | 43 | #### Defined in 44 | 45 | [constants.ts:28](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L28) 46 | 47 | ___ 48 | 49 | ### Pending 50 | 51 | • **Pending** = "Pending" 52 | 53 | #### Defined in 54 | 55 | [constants.ts:26](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L26) 56 | 57 | ___ 58 | 59 | ### Uninitialized 60 | 61 | • **Uninitialized** = "Uninitialized" 62 | 63 | #### Defined in 64 | 65 | [constants.ts:25](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L25) 66 | -------------------------------------------------------------------------------- /docs/modules/constants.md: -------------------------------------------------------------------------------- 1 | [zilswap-sdk](../README.md) / [Exports](../modules.md) / constants 2 | 3 | # Module: constants 4 | 5 | ## Table of contents 6 | 7 | ### Enumerations 8 | 9 | - [ILOState](../enums/constants.ilostate.md) 10 | - [Network](../enums/constants.network.md) 11 | 12 | ### Variables 13 | 14 | - [APIS](constants.md#apis) 15 | - [BASIS](constants.md#basis) 16 | - [CHAIN\_VERSIONS](constants.md#chain_versions) 17 | - [CONTRACTS](constants.md#contracts) 18 | - [WSS](constants.md#wss) 19 | - [ZIL\_HASH](constants.md#zil_hash) 20 | 21 | ## Variables 22 | 23 | ### APIS 24 | 25 | • `Const` **APIS**: { [key in Networks]: string} 26 | 27 | #### Defined in 28 | 29 | [constants.ts:9](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L9) 30 | 31 | ___ 32 | 33 | ### BASIS 34 | 35 | • `Const` **BASIS**: ``10000`` 36 | 37 | #### Defined in 38 | 39 | [constants.ts:37](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L37) 40 | 41 | ___ 42 | 43 | ### CHAIN\_VERSIONS 44 | 45 | • `Const` **CHAIN\_VERSIONS**: { [key in Networks]: number} 46 | 47 | #### Defined in 48 | 49 | [constants.ts:32](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L32) 50 | 51 | ___ 52 | 53 | ### CONTRACTS 54 | 55 | • `Const` **CONTRACTS**: { [key in Networks]: string} 56 | 57 | #### Defined in 58 | 59 | [constants.ts:19](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L19) 60 | 61 | ___ 62 | 63 | ### WSS 64 | 65 | • `Const` **WSS**: { [key in Networks]: string} 66 | 67 | #### Defined in 68 | 69 | [constants.ts:14](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L14) 70 | 71 | ___ 72 | 73 | ### ZIL\_HASH 74 | 75 | • `Const` **ZIL\_HASH**: ``"0x0000000000000000000000000000000000000000"`` 76 | 77 | #### Defined in 78 | 79 | [constants.ts:39](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/constants.ts#L39) 80 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | import { bytes } from '@zilliqa-js/util' 2 | 3 | export enum Network { 4 | MainNet = 'MainNet', 5 | TestNet = 'TestNet', 6 | } 7 | type Networks = keyof typeof Network 8 | 9 | export const APIS: { [key in Networks]: string } = { 10 | [Network.MainNet]: 'https://api.zilliqa.com', 11 | [Network.TestNet]: 'https://dev-api.zilliqa.com', 12 | } 13 | 14 | export const WSS: { [key in Networks]: string } = { 15 | [Network.MainNet]: 'wss://api-ws.zilliqa.com', 16 | [Network.TestNet]: 'wss://dev-ws.zilliqa.com', 17 | } 18 | 19 | export const CONTRACTS: { [key in Networks]: string } = { 20 | [Network.MainNet]: 'zil1gkwt95a67lnpe774lcmz72y6ay4jh2asmmjw6u', 21 | [Network.TestNet]: 'zil1rf3dm8yykryffr94rlrxfws58earfxzu5lw792', 22 | } 23 | 24 | export const ARK_CONTRACTS: { [key in Networks]: string } = { 25 | [Network.MainNet]: '', 26 | [Network.TestNet]: 'zil1sgf3zpgt6qeflg053pxjwx9s9pxclx3p7s06gp', 27 | } 28 | 29 | export const WHITELISTED_TOKENS: { [key in Networks]: string[] } = { 30 | [Network.MainNet]: [ 31 | 'zil1gvr0jgwfsfmxsyx0xsnhtlte4gks6r3yk8x5fn', // wZIL 32 | 'zil1p5suryq6q647usxczale29cu3336hhp376c627', // ZWAP 33 | 'zil1zu72vac254htqpg3mtywdcfm84l3dfd9qzww8t', // XSGD 34 | 'zil14pzuzq6v6pmmmrfjhczywguu0e97djepxt8g3e', // gZIL 35 | 'zil1sxx29cshups269ahh5qjffyr58mxjv9ft78jqy', // zUSDT 36 | 'zil1wha8mzaxhm22dpm5cav2tepuldnr8kwkvmqtjq', // zWBTC 37 | 'zil19j33tapjje2xzng7svslnsjjjgge930jx0w09v', // zETH 38 | 'zil1yk93f957fanapf0yszgm84p62xrxxfytj4d2tl', // SWTH 39 | ], 40 | [Network.TestNet]: [], 41 | } 42 | 43 | export enum ILOState { 44 | Uninitialized = 'Uninitialized', 45 | Pending = 'Pending', 46 | Active = 'Active', 47 | Failed = 'Failed', 48 | Completed = 'Completed', 49 | } 50 | 51 | export const CHAIN_VERSIONS: { [key in Networks]: number } = { 52 | [Network.MainNet]: bytes.pack(1, 1), 53 | [Network.TestNet]: bytes.pack(333, 1), 54 | } 55 | 56 | export const BASIS = 10000 57 | 58 | export const ZIL_HASH = '0x0000000000000000000000000000000000000000' 59 | -------------------------------------------------------------------------------- /docs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # CONTRIBUTING 2 | 3 | ## How to contribute to Zilswap SDK 4 | 5 | ### **Do you intend to add your project's token logo?** 6 | 7 | Please visit the [zilswap token list](https://github.com/Switcheo/zilswap-token-list) to add your token logo. This repository only hosts the Zilswap UI source code. 8 | 9 | ### **Did you find a bug?** 10 | 11 | * **Do not open up a GitHub issue if the bug is a security vulnerability 12 | in the Zilswap SDK or smart contract**, and instead to send an email to [security@switcheo.network](mailto:https://security@switcheo.network). 13 | 14 | * **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/Switcheo/zilswap-sdk/issues). 15 | 16 | * If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/Switcheo/zilswap-sdk/issues/new). 17 | Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or 18 | an **executable test case** demonstrating the expected behavior that is not occurring. 19 | 20 | * If possible, use the relevant bug report templates to create the issue. 21 | 22 | ### **Did you write a patch that fixes a bug?** 23 | 24 | * Open a new GitHub pull request with the patch. 25 | 26 | * Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable. 27 | 28 | ### **Did you fix whitespace, format code, or make a purely cosmetic patch?** 29 | 30 | Changes that are cosmetic in nature and do not add anything substantial to the stability, functionality, or testability of Zilswap will generally not be accepted. 31 | 32 | ### **Do you intend to add a new feature or change an existing one?** 33 | 34 | * Suggest your change in the [zilswap discord channel](https://discord.gg/5n8AMQH) and start writing code. 35 | 36 | * Do not open an issue on GitHub until you have collected positive feedback about the change. GitHub issues are primarily intended for bug reports and fixes. 37 | 38 | ### **Do you want to contribute to the Zilswap UI or documentation?** 39 | 40 | * Please see [https://github.com/Switcheo/zilswap-webapp/blob/master/CONTRIBUTING.md] to contribute to the Zilswap UI. 41 | 42 | * Please see [https://github.com/Switcheo/zilswap/blob/master/CONTRIBUTING.md] to contribute to the Zilswap docuemntation. 43 | 44 | ### **Do you have questions about the source code?** 45 | 46 | Ask any question about how to use Zilswap in the [zilswap discord channel](https://discord.gg/5n8AMQH). 47 | -------------------------------------------------------------------------------- /docs/modules/utils.md: -------------------------------------------------------------------------------- 1 | [zilswap-sdk](../README.md) / [Exports](../modules.md) / utils 2 | 3 | # Module: utils 4 | 5 | ## Table of contents 6 | 7 | ### Functions 8 | 9 | - [contractInitToMap](utils.md#contractinittomap) 10 | - [isLocalStorageAvailable](utils.md#islocalstorageavailable) 11 | - [toPositiveQa](utils.md#topositiveqa) 12 | - [unitlessBigNumber](utils.md#unitlessbignumber) 13 | 14 | ## Functions 15 | 16 | ### contractInitToMap 17 | 18 | ▸ `Const` **contractInitToMap**(`params`): `Object` 19 | 20 | Converts `Value[]` array to map of string values. 21 | `Value.type` is ignored, all values are returned as string. 22 | 23 | sample input: 24 | ```javascript 25 | [{ 26 | name: 'address', 27 | type: 'ByStr20', 28 | value: '0xbadbeef', 29 | }, { 30 | name: 'balance', 31 | type: 'UInt28', 32 | value: '100000000', 33 | }] 34 | ``` 35 | 36 | output: 37 | ```javascript 38 | { 39 | address: '0xbadbeef', 40 | balance: '100000000', 41 | } 42 | ``` 43 | 44 | #### Parameters 45 | 46 | | Name | Type | Description | 47 | | :------ | :------ | :------ | 48 | | `params` | `Value`[] | parameters in `Value[]` array representation | 49 | 50 | #### Returns 51 | 52 | `Object` 53 | 54 | mapped object representation - refer to sample output 55 | 56 | #### Defined in 57 | 58 | [utils.ts:150](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/utils.ts#L150) 59 | 60 | ___ 61 | 62 | ### isLocalStorageAvailable 63 | 64 | ▸ `Const` **isLocalStorageAvailable**(): `boolean` 65 | 66 | #### Returns 67 | 68 | `boolean` 69 | 70 | #### Defined in 71 | 72 | [utils.ts:100](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/utils.ts#L100) 73 | 74 | ___ 75 | 76 | ### toPositiveQa 77 | 78 | ▸ `Const` **toPositiveQa**(`input`, `unitOrDecimals`): `BN` 79 | 80 | #### Parameters 81 | 82 | | Name | Type | 83 | | :------ | :------ | 84 | | `input` | `string` \| `number` \| `BN` | 85 | | `unitOrDecimals` | `number` \| `Zil` \| `Li` \| `Qa` | 86 | 87 | #### Returns 88 | 89 | `BN` 90 | 91 | #### Defined in 92 | 93 | [utils.ts:40](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/utils.ts#L40) 94 | 95 | ___ 96 | 97 | ### unitlessBigNumber 98 | 99 | ▸ `Const` **unitlessBigNumber**(`str`): `BigNumber` 100 | 101 | #### Parameters 102 | 103 | | Name | Type | 104 | | :------ | :------ | 105 | | `str` | `string` | 106 | 107 | #### Returns 108 | 109 | `BigNumber` 110 | 111 | #### Defined in 112 | 113 | [utils.ts:32](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/utils.ts#L32) 114 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Zilswap Typescript SDK 2 | 3 | ## Setup 4 | 5 | Install from npm: 6 | 7 | `npm install zilswap-sdk` 8 | 9 | ## SDK Usage 10 | 11 | Initialize the sdk based on the required network, then call the required methods which will automatically map and call the corresponding smart contract correct transitions. 12 | 13 | ```ts 14 | import { Zilswap } from 'zilswap-sdk' 15 | 16 | (async () => { 17 | const zilswap = new Zilswap(Network.TestNet) 18 | await zilswap.initialize() 19 | await zilswap.addLiquidity('SWTH', '42', '42') 20 | await zilswap.teardown() 21 | })() 22 | ``` 23 | 24 | ### Methods 25 | 26 | All public Zilswap methods can be found on the [`Zilswap` SDK object](classes/index.zilswap.md). 27 | 28 | All public Zilo methods can be found on the [`Zilo` SDK object](classes/zilo.zilo-1.md). 29 | 30 | Full typescript definitions can also be found in the [Modules](modules.md). 31 | 32 | The following is a list of methods to quickly get you started: 33 | 34 | #### Swap & Liquidity 35 | 36 | - `approveTokenTransferIfRequired` - approves transfers to zilswap for the given token contract, if the current approval amount is insufficient. 37 | - `addLiquidity` - adds liquidity to the pool 38 | - `removeLiquidity` - removes liquidity to the pool 39 | - `swapWithExactInput` - swaps a token for another token, specifying the exact amount that should be given. 40 | - `swapWithExactOutput` - swaps a token for another token, specifying the exact amount that should be received. 41 | 42 | #### Getters 43 | 44 | - `getAppState` - gets the current dApp state 45 | - `getPool` - gets the reserve values for a pool 46 | - `getObservedTxs` - gets the txs that the SDK is observing 47 | 48 | #### Configuration 49 | 50 | - `addToken` - adds a token that is not in the pre-built list 51 | - `observeTx` - observe a zilliqa blockchain tx 52 | - `setDeadlineBlocks` - set the number of blocks before a transition sent by the SDK to expires 53 | 54 | #### Helpers 55 | 56 | - `toUnitless` - converts a human amount into a unitless integer that is used by Scilla. 57 | - `toUnit` - converts a unitless integer used by scilla into a human readable amount. 58 | - `getRatesForInput` - get the current exchange rates for a pool by giving an input amount. 59 | - `getRatesForOutput` - get the current exchange rates for a pool by giving an output amount. 60 | 61 | ## Test Usage 62 | 63 | 1. Ensure enough tokens minted to your address on testnet 64 | 2. Run `PRIVATE_KEY=xxx yarn run test` 65 | 66 | ## Developing 67 | 68 | Generate documentation with typedoc. Install with: 69 | 70 | `npm i typedoc typedoc-plugin-markdown --global` 71 | 72 | then run: 73 | 74 | `typedoc --out ./doc ./src --excludePrivate --excludeNotExported --plugin typedoc-plugin-markdown` 75 | 76 | ## Contributing 77 | 78 | Please review the [contribution guidelines](./CONTRIBUTING.md) before contributing or opening pull requests. 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zilswap Typescript SDK 2 | 3 | ## Setup 4 | 5 | Install from npm: 6 | 7 | `npm install zilswap-sdk` 8 | 9 | ## SDK Usage 10 | 11 | Initialize the sdk based on the required network, then call the required methods which will automatically map and call the corresponding smart contract correct transitions. 12 | 13 | ```ts 14 | import { Zilswap } from 'zilswap-sdk' 15 | 16 | (async () => { 17 | const zilswap = new Zilswap(Network.TestNet) 18 | await zilswap.initialize() 19 | await zilswap.addLiquidity('SWTH', '42', '42') 20 | await zilswap.teardown() 21 | })() 22 | ``` 23 | 24 | ### Methods 25 | 26 | All public Zilswap methods can be found on the [`Zilswap` SDK object](./docs/classes/index.zilswap.md). 27 | 28 | All public Zilo methods can be found on the [`Zilo` SDK object](./docs/classes/zilo.zilo-1.md). 29 | 30 | Full typescript definitions can also be found in the [Modules](./docs/modules.md). 31 | 32 | The following is a list of methods to quickly get you started: 33 | 34 | #### Swap & Liquidity 35 | 36 | - `approveTokenTransferIfRequired` - approves transfers to zilswap for the given token contract, if the current approval amount is insufficient. 37 | - `addLiquidity` - adds liquidity to the pool 38 | - `removeLiquidity` - removes liquidity to the pool 39 | - `swapWithExactInput` - swaps a token for another token, specifying the exact amount that should be given. 40 | - `swapWithExactOutput` - swaps a token for another token, specifying the exact amount that should be received. 41 | 42 | #### Getters 43 | 44 | - `getAppState` - gets the current dApp state 45 | - `getPool` - gets the reserve values for a pool 46 | - `getObservedTxs` - gets the txs that the SDK is observing 47 | 48 | #### Configuration 49 | 50 | - `addToken` - adds a token that is not in the pre-built list 51 | - `observeTx` - observe a zilliqa blockchain tx 52 | - `setDeadlineBlocks` - set the number of blocks before a transition sent by the SDK to expires 53 | 54 | #### Helpers 55 | 56 | - `toUnitless` - converts a human amount into a unitless integer that is used by Scilla. 57 | - `toUnit` - converts a unitless integer used by scilla into a human readable amount. 58 | - `getRatesForInput` - get the current exchange rates for a pool by giving an input amount. 59 | - `getRatesForOutput` - get the current exchange rates for a pool by giving an output amount. 60 | 61 | ## Test Usage 62 | 63 | 1. Ensure enough tokens minted to your address on testnet 64 | 2. Run `PRIVATE_KEY=xxx yarn run test` 65 | 66 | ## Developing 67 | 68 | Generate documentation with typedoc. Install with: 69 | 70 | `npm i typedoc typedoc-plugin-markdown --global` 71 | 72 | then run: 73 | 74 | `typedoc --out ./doc ./src --excludePrivate --excludeNotExported --plugin typedoc-plugin-markdown` 75 | 76 | ## Contributing 77 | 78 | Please review the [contribution guidelines](docs/CONTRIBUTING.md) before contributing or opening pull requests. 79 | -------------------------------------------------------------------------------- /docs/modules/zilo.md: -------------------------------------------------------------------------------- 1 | [zilswap-sdk](../README.md) / [Exports](../modules.md) / zilo 2 | 3 | # Module: zilo 4 | 5 | ## Table of contents 6 | 7 | ### Classes 8 | 9 | - [Zilo](../classes/zilo.zilo-1.md) 10 | 11 | ### Type aliases 12 | 13 | - [OnStateUpdate](zilo.md#onstateupdate) 14 | - [ZiloAppState](zilo.md#ziloappstate) 15 | - [ZiloContractInit](zilo.md#zilocontractinit) 16 | - [ZiloContractState](zilo.md#zilocontractstate) 17 | 18 | ## Type aliases 19 | 20 | ### OnStateUpdate 21 | 22 | Ƭ **OnStateUpdate**: (`appState`: [ZiloAppState](zilo.md#ziloappstate)) => `void` 23 | 24 | #### Type declaration 25 | 26 | ▸ (`appState`): `void` 27 | 28 | ##### Parameters 29 | 30 | | Name | Type | 31 | | :------ | :------ | 32 | | `appState` | [ZiloAppState](zilo.md#ziloappstate) | 33 | 34 | ##### Returns 35 | 36 | `void` 37 | 38 | #### Defined in 39 | 40 | [zilo.ts:14](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L14) 41 | 42 | ___ 43 | 44 | ### ZiloAppState 45 | 46 | Ƭ **ZiloAppState**: `Object` 47 | 48 | #### Type declaration 49 | 50 | | Name | Type | 51 | | :------ | :------ | 52 | | `claimable` | `boolean` | 53 | | `contractInit` | [ZiloContractInit](zilo.md#zilocontractinit) \| ``null`` | 54 | | `contractState` | [ZiloContractState](zilo.md#zilocontractstate) | 55 | | `contributed` | `boolean` | 56 | | `currentNonce` | `number` \| ``null`` | 57 | | `currentUser` | `string` \| ``null`` | 58 | | `state` | [ILOState](../enums/constants.ilostate.md) | 59 | | `userContribution` | `BigNumber` | 60 | 61 | #### Defined in 62 | 63 | [zilo.ts:39](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L39) 64 | 65 | ___ 66 | 67 | ### ZiloContractInit 68 | 69 | Ƭ **ZiloContractInit**: `Object` 70 | 71 | #### Type declaration 72 | 73 | | Name | Type | 74 | | :------ | :------ | 75 | | `_creation_block` | `string` | 76 | | `_scilla_version` | `string` | 77 | | `_this_address` | `string` | 78 | | `end_block` | `number` | 79 | | `liquidity_address` | `string` | 80 | | `liquidity_zil_amount` | `BigNumber` | 81 | | `minimum_zil_amount` | `BigNumber` | 82 | | `receiver_address` | `string` | 83 | | `start_block` | `number` | 84 | | `target_zil_amount` | `BigNumber` | 85 | | `target_zwap_amount` | `BigNumber` | 86 | | `token_address` | `string` | 87 | | `token_amount` | `BigNumber` | 88 | | `zwap_address` | `string` | 89 | 90 | #### Defined in 91 | 92 | [zilo.ts:22](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L22) 93 | 94 | ___ 95 | 96 | ### ZiloContractState 97 | 98 | Ƭ **ZiloContractState**: `Object` 99 | 100 | #### Type declaration 101 | 102 | | Name | Type | 103 | | :------ | :------ | 104 | | `contributions` | `Object` | 105 | | `initialized` | `ADTValue` | 106 | | `total_contributions` | `string` | 107 | 108 | #### Defined in 109 | 110 | [zilo.ts:16](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L16) 111 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at engineering@switcheo.network. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /docs/classes/zilo.zilo-1.md: -------------------------------------------------------------------------------- 1 | [zilswap-sdk](../README.md) / [Exports](../modules.md) / [zilo](../modules/zilo.md) / Zilo 2 | 3 | # Class: Zilo 4 | 5 | [zilo](../modules/zilo.md) 6 | 7 | Zilo class to represent an instance of a ZilSwap Initial Launch Offering. 8 | 9 | Usage: 10 | ``` 11 | const zilswap = new Zilswap(Network.TestNet) 12 | await zilswap.initialize() 13 | const zilo = await zilswap.registerZilo(ZILO_ADDRESS, ziloStateObserver) 14 | 15 | const ziloState = zilo.getZiloState() 16 | 17 | if (ziloState.state === ILOState.Active) { 18 | const amount = new BigNumber(1).shiftedBy(ZIL_DECIMALS).toString(10) 19 | const tx = await zilo.contribute(amount) 20 | 21 | console.log("distribute TX sent", tx.hash) 22 | } else { 23 | console.log("ZILO not yet active") 24 | } 25 | ``` 26 | 27 | ## Table of contents 28 | 29 | ### Constructors 30 | 31 | - [constructor](zilo.zilo-1.md#constructor) 32 | 33 | ### Methods 34 | 35 | - [claim](zilo.zilo-1.md#claim) 36 | - [complete](zilo.zilo-1.md#complete) 37 | - [contribute](zilo.zilo-1.md#contribute) 38 | - [getZiloState](zilo.zilo-1.md#getzilostate) 39 | - [initialize](zilo.zilo-1.md#initialize) 40 | - [updateBlockHeight](zilo.zilo-1.md#updateblockheight) 41 | - [updateObserver](zilo.zilo-1.md#updateobserver) 42 | - [updateZiloState](zilo.zilo-1.md#updatezilostate) 43 | 44 | ## Constructors 45 | 46 | ### constructor 47 | 48 | • **new Zilo**(`zilswap`, `address`) 49 | 50 | #### Parameters 51 | 52 | | Name | Type | 53 | | :------ | :------ | 54 | | `zilswap` | [Zilswap](index.zilswap.md) | 55 | | `address` | `string` | 56 | 57 | #### Defined in 58 | 59 | [zilo.ts:76](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L76) 60 | 61 | ## Methods 62 | 63 | ### claim 64 | 65 | ▸ **claim**(): `Promise`<``null`` \| [ObservedTx](../modules/index.md#observedtx)\> 66 | 67 | Execute claim function if user contributed 68 | 69 | #### Returns 70 | 71 | `Promise`<``null`` \| [ObservedTx](../modules/index.md#observedtx)\> 72 | 73 | #### Defined in 74 | 75 | [zilo.ts:223](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L223) 76 | 77 | ___ 78 | 79 | ### complete 80 | 81 | ▸ **complete**(): `Promise`<``null`` \| [ObservedTx](../modules/index.md#observedtx)\> 82 | 83 | #### Returns 84 | 85 | `Promise`<``null`` \| [ObservedTx](../modules/index.md#observedtx)\> 86 | 87 | #### Defined in 88 | 89 | [zilo.ts:254](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L254) 90 | 91 | ___ 92 | 93 | ### contribute 94 | 95 | ▸ **contribute**(`amountToContributeStr`): `Promise`<``null`` \| [ObservedTx](../modules/index.md#observedtx)\> 96 | 97 | Contribute to the ILO, may need to increase token allowance before proceeding 98 | 99 | #### Parameters 100 | 101 | | Name | Type | Description | 102 | | :------ | :------ | :------ | 103 | | `amountToContributeStr` | `string` | is the exact amount of ZIL to be contribute as a unitless string (without decimals). | 104 | 105 | #### Returns 106 | 107 | `Promise`<``null`` \| [ObservedTx](../modules/index.md#observedtx)\> 108 | 109 | #### Defined in 110 | 111 | [zilo.ts:285](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L285) 112 | 113 | ___ 114 | 115 | ### getZiloState 116 | 117 | ▸ **getZiloState**(): [ZiloAppState](../modules/zilo.md#ziloappstate) 118 | 119 | #### Returns 120 | 121 | [ZiloAppState](../modules/zilo.md#ziloappstate) 122 | 123 | #### Defined in 124 | 125 | [zilo.ts:178](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L178) 126 | 127 | ___ 128 | 129 | ### initialize 130 | 131 | ▸ **initialize**(`observer?`): `Promise` 132 | 133 | #### Parameters 134 | 135 | | Name | Type | 136 | | :------ | :------ | 137 | | `observer?` | [OnStateUpdate](../modules/zilo.md#onstateupdate) | 138 | 139 | #### Returns 140 | 141 | `Promise` 142 | 143 | #### Defined in 144 | 145 | [zilo.ts:83](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L83) 146 | 147 | ___ 148 | 149 | ### updateBlockHeight 150 | 151 | ▸ **updateBlockHeight**(`height?`): `Promise` 152 | 153 | #### Parameters 154 | 155 | | Name | Type | 156 | | :------ | :------ | 157 | | `height?` | `number` | 158 | 159 | #### Returns 160 | 161 | `Promise` 162 | 163 | #### Defined in 164 | 165 | [zilo.ts:160](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L160) 166 | 167 | ___ 168 | 169 | ### updateObserver 170 | 171 | ▸ **updateObserver**(`observer?`): `void` 172 | 173 | #### Parameters 174 | 175 | | Name | Type | 176 | | :------ | :------ | 177 | | `observer?` | [OnStateUpdate](../modules/zilo.md#onstateupdate) | 178 | 179 | #### Returns 180 | 181 | `void` 182 | 183 | #### Defined in 184 | 185 | [zilo.ts:88](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L88) 186 | 187 | ___ 188 | 189 | ### updateZiloState 190 | 191 | ▸ **updateZiloState**(): `Promise` 192 | 193 | #### Returns 194 | 195 | `Promise` 196 | 197 | #### Defined in 198 | 199 | [zilo.ts:126](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/zilo.ts#L126) 200 | -------------------------------------------------------------------------------- /docs/modules/index.md: -------------------------------------------------------------------------------- 1 | [zilswap-sdk](../README.md) / [Exports](../modules.md) / index 2 | 3 | # Module: index 4 | 5 | ## Table of contents 6 | 7 | ### References 8 | 9 | - [Zilo](index.md#zilo) 10 | 11 | ### Classes 12 | 13 | - [Zilswap](../classes/index.zilswap.md) 14 | 15 | ### Type aliases 16 | 17 | - [AppState](index.md#appstate) 18 | - [ContractState](index.md#contractstate) 19 | - [ObservedTx](index.md#observedtx) 20 | - [OnUpdate](index.md#onupdate) 21 | - [Options](index.md#options) 22 | - [Pool](index.md#pool) 23 | - [Rates](index.md#rates) 24 | - [TokenDetails](index.md#tokendetails) 25 | - [TxParams](index.md#txparams) 26 | - [TxReceipt](index.md#txreceipt) 27 | - [TxStatus](index.md#txstatus) 28 | - [WalletProvider](index.md#walletprovider) 29 | 30 | ## References 31 | 32 | ### Zilo 33 | 34 | Renames and exports: [zilo](zilo.md) 35 | 36 | ## Type aliases 37 | 38 | ### AppState 39 | 40 | Ƭ **AppState**: `Object` 41 | 42 | #### Type declaration 43 | 44 | | Name | Type | 45 | | :------ | :------ | 46 | | `contractState` | [ContractState](index.md#contractstate) | 47 | | `currentBalance` | `BigNumber` \| ``null`` | 48 | | `currentNonce` | `number` \| ``null`` | 49 | | `currentUser` | `string` \| ``null`` | 50 | | `pools` | { [key in string]?: Pool} | 51 | | `tokens` | { [key in string]: TokenDetails} | 52 | 53 | #### Defined in 54 | 55 | [index.ts:64](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L64) 56 | 57 | ___ 58 | 59 | ### ContractState 60 | 61 | Ƭ **ContractState**: `Object` 62 | 63 | #### Type declaration 64 | 65 | | Name | Type | 66 | | :------ | :------ | 67 | | `balances` | { [key in string]?: { [key2 in string]?: string}} | 68 | | `output_after_fee` | `string` | 69 | | `pools` | { [key in string]?: object} | 70 | | `total_contributions` | { [key in string]?: string} | 71 | 72 | #### Defined in 73 | 74 | [index.ts:57](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L57) 75 | 76 | ___ 77 | 78 | ### ObservedTx 79 | 80 | Ƭ **ObservedTx**: `Object` 81 | 82 | #### Type declaration 83 | 84 | | Name | Type | 85 | | :------ | :------ | 86 | | `deadline` | `number` | 87 | | `hash` | `string` | 88 | 89 | #### Defined in 90 | 91 | [index.ts:28](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L28) 92 | 93 | ___ 94 | 95 | ### OnUpdate 96 | 97 | Ƭ **OnUpdate**: (`tx`: [ObservedTx](index.md#observedtx), `status`: [TxStatus](index.md#txstatus), `receipt?`: [TxReceipt](index.md#txreceipt)) => `void` 98 | 99 | #### Type declaration 100 | 101 | ▸ (`tx`, `status`, `receipt?`): `void` 102 | 103 | ##### Parameters 104 | 105 | | Name | Type | 106 | | :------ | :------ | 107 | | `tx` | [ObservedTx](index.md#observedtx) | 108 | | `status` | [TxStatus](index.md#txstatus) | 109 | | `receipt?` | [TxReceipt](index.md#txreceipt) | 110 | 111 | ##### Returns 112 | 113 | `void` 114 | 115 | #### Defined in 116 | 117 | [index.ts:26](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L26) 118 | 119 | ___ 120 | 121 | ### Options 122 | 123 | Ƭ **Options**: `Object` 124 | 125 | #### Type declaration 126 | 127 | | Name | Type | 128 | | :------ | :------ | 129 | | `deadlineBuffer?` | `number` | 130 | | `gasLimit?` | `number` | 131 | | `gasPrice?` | `number` | 132 | | `rpcEndpoint?` | `string` | 133 | 134 | #### Defined in 135 | 136 | [index.ts:19](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L19) 137 | 138 | ___ 139 | 140 | ### Pool 141 | 142 | Ƭ **Pool**: `Object` 143 | 144 | #### Type declaration 145 | 146 | | Name | Type | 147 | | :------ | :------ | 148 | | `contributionPercentage` | `BigNumber` | 149 | | `exchangeRate` | `BigNumber` | 150 | | `tokenReserve` | `BigNumber` | 151 | | `totalContribution` | `BigNumber` | 152 | | `userContribution` | `BigNumber` | 153 | | `zilReserve` | `BigNumber` | 154 | 155 | #### Defined in 156 | 157 | [index.ts:73](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L73) 158 | 159 | ___ 160 | 161 | ### Rates 162 | 163 | Ƭ **Rates**: `Object` 164 | 165 | #### Type declaration 166 | 167 | | Name | Type | 168 | | :------ | :------ | 169 | | `expectedAmount` | `BigNumber` | 170 | | `slippage` | `BigNumber` | 171 | 172 | #### Defined in 173 | 174 | [index.ts:82](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L82) 175 | 176 | ___ 177 | 178 | ### TokenDetails 179 | 180 | Ƭ **TokenDetails**: `Object` 181 | 182 | #### Type declaration 183 | 184 | | Name | Type | 185 | | :------ | :------ | 186 | | `address` | `string` | 187 | | `contract` | `Contract` | 188 | | `decimals` | `number` | 189 | | `hash` | `string` | 190 | | `registered` | `boolean` | 191 | | `symbol` | `string` | 192 | | `whitelisted` | `boolean` | 193 | 194 | #### Defined in 195 | 196 | [index.ts:47](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L47) 197 | 198 | ___ 199 | 200 | ### TxParams 201 | 202 | Ƭ **TxParams**: `Object` 203 | 204 | #### Type declaration 205 | 206 | | Name | Type | 207 | | :------ | :------ | 208 | | `gasLimit` | `Long` | 209 | | `gasPrice` | `BN` | 210 | | `version` | `number` | 211 | 212 | #### Defined in 213 | 214 | [index.ts:41](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L41) 215 | 216 | ___ 217 | 218 | ### TxReceipt 219 | 220 | Ƭ **TxReceipt**: `\_TxReceipt` 221 | 222 | #### Defined in 223 | 224 | [index.ts:39](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L39) 225 | 226 | ___ 227 | 228 | ### TxStatus 229 | 230 | Ƭ **TxStatus**: ``"confirmed"`` \| ``"rejected"`` \| ``"expired"`` 231 | 232 | #### Defined in 233 | 234 | [index.ts:37](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L37) 235 | 236 | ___ 237 | 238 | ### WalletProvider 239 | 240 | Ƭ **WalletProvider**: `Omit`<`Zilliqa` & { `wallet`: `Wallet` & { `defaultAccount`: { `base16`: `string` ; `bech32`: `string` } ; `net`: `string` } }, ``"subscriptionBuilder"``\> 241 | 242 | #### Defined in 243 | 244 | [index.ts:87](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L87) 245 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "src/**/*" 4 | ], 5 | "compilerOptions": { 6 | /* Basic Options */ 7 | // "incremental": true, /* Enable incremental compilation */ 8 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 9 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 10 | // "lib": [], /* Specify library files to be included in the compilation. */ 11 | // "allowJs": true, /* Allow javascript files to be compiled. */ 12 | // "checkJs": true, /* Report errors in .js files. */ 13 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 14 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 15 | "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 16 | "sourceMap": true, /* Generates corresponding '.map' file. */ 17 | // "outFile": "./", /* Concatenate and emit output to single file. */ 18 | "outDir": "./lib", /* Redirect output structure to the directory. */ 19 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 20 | // "composite": true, /* Enable project compilation */ 21 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 22 | // "removeComments": true, /* Do not emit comments to output. */ 23 | // "noEmit": true, /* Do not emit outputs. */ 24 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 25 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 26 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 27 | 28 | /* Strict Type-Checking Options */ 29 | "strict": true, /* Enable all strict type-checking options. */ 30 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 31 | // "strictNullChecks": true, /* Enable strict null checks. */ 32 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 33 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 34 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 35 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 36 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 37 | 38 | /* Additional Checks */ 39 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 40 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 41 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 42 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 43 | 44 | /* Module Resolution Options */ 45 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 46 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 47 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 48 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 49 | // "typeRoots": [], /* List of folders to include type definitions from. */ 50 | // "types": [], /* Type declaration files to be included in compilation. */ 51 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 52 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 53 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 54 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 55 | 56 | /* Source Map Options */ 57 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 58 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 59 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 60 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 61 | 62 | /* Experimental Options */ 63 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 64 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 65 | 66 | /* Advanced Options */ 67 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { Value } from '@zilliqa-js/contract' 2 | import { fromBech32Address } from '@zilliqa-js/crypto' 3 | import { BN, units } from '@zilliqa-js/util' 4 | import { BigNumber } from 'bignumber.js' 5 | import { Network, ARK_CONTRACTS, ZIL_HASH } from './constants' 6 | import crypto from 'crypto' 7 | 8 | BigNumber.config({ EXPONENTIAL_AT: 1e9 }) // never! 9 | 10 | // The following code is based on: @zilliqa-js/util/src/unit.ts. 11 | // toPositiveQa is modified from toQa to accept arbitrary number units, 12 | // while not accepting negative inputs. 13 | 14 | const unitMap = new Map([ 15 | [units.Units.Qa, '1'], 16 | [units.Units.Li, '1000000'], // 1e6 qa 17 | [units.Units.Zil, '1000000000000'], // 1e12 qa 18 | ]) 19 | 20 | const numToStr = (input: string | number | BN) => { 21 | if (typeof input === 'string') { 22 | if (!input.match(/^-?[0-9.]+$/)) { 23 | throw new Error(`while converting number to string, invalid number value '${input}', should be a number matching (^[0-9.]+).`) 24 | } 25 | return input 26 | } else if (typeof input === 'number') { 27 | return String(input) 28 | } else if (BN.isBN(input)) { 29 | return input.toString(10) 30 | } 31 | 32 | throw new Error(`while converting number to string, invalid number value '${input}' type ${typeof input}.`) 33 | } 34 | 35 | export const unitlessBigNumber = (str: string): BigNumber => { 36 | const bn = new BigNumber(str) 37 | if (!bn.integerValue().isEqualTo(bn)) { 38 | throw new Error(`number ${bn} should be unitless (no decimals).`) 39 | } 40 | return bn 41 | } 42 | 43 | export const toPositiveQa = (input: string | number | BN, unitOrDecimals: units.Units | number) => { 44 | const inputStr = numToStr(input) 45 | 46 | let base: BN 47 | let baseNumDecimals: number 48 | 49 | if (typeof unitOrDecimals === 'number') { 50 | // decimals 51 | if (unitOrDecimals < 0 || unitOrDecimals % 1 !== 0) { 52 | throw new Error(`Invalid decimals ${unitOrDecimals}, must be non-negative integer.`) 53 | } 54 | 55 | baseNumDecimals = unitOrDecimals 56 | base = new BN(10).pow(new BN(baseNumDecimals)) 57 | } else { 58 | // unit 59 | const baseStr = unitMap.get(unitOrDecimals) 60 | 61 | if (!baseStr) { 62 | throw new Error(`No unit of type ${unitOrDecimals} exists.`) 63 | } 64 | 65 | baseNumDecimals = baseStr.length - 1 66 | base = new BN(baseStr, 10) 67 | } 68 | 69 | if (inputStr === '.') { 70 | throw new Error(`Cannot convert ${inputStr} to Qa.`) 71 | } 72 | 73 | // Split it into a whole and fractional part 74 | const comps = inputStr.split('.') 75 | if (comps.length > 2) { 76 | throw new Error(`Cannot convert ${inputStr} to Qa.`) 77 | } 78 | 79 | let [whole, fraction] = comps 80 | 81 | if (!whole) { 82 | whole = '0' 83 | } 84 | if (!fraction) { 85 | fraction = '0' 86 | } 87 | if (fraction.length > baseNumDecimals) { 88 | throw new Error(`Cannot convert ${inputStr} to Qa.`) 89 | } 90 | 91 | while (fraction.length < baseNumDecimals) { 92 | fraction += '0' 93 | } 94 | 95 | const wholeBN = new BN(whole) 96 | const fractionBN = new BN(fraction) 97 | const qa = wholeBN.mul(base).add(fractionBN) 98 | 99 | return new BN(qa.toString(10), 10) 100 | } 101 | 102 | let _lsAvailable: boolean | null = null 103 | export const isLocalStorageAvailable = () => { 104 | if (_lsAvailable !== null) { 105 | // only check for ls once 106 | return _lsAvailable 107 | } 108 | 109 | _lsAvailable = false 110 | if (typeof localStorage !== 'undefined') { 111 | try { 112 | localStorage.setItem('ls_feature_test', 'yes') 113 | if (localStorage.getItem('ls_feature_test') === 'yes') { 114 | localStorage.removeItem('ls_feature_test') 115 | _lsAvailable = true 116 | } 117 | } catch (e) { 118 | // fall-through as `false` 119 | } 120 | } 121 | return _lsAvailable 122 | } 123 | 124 | /** 125 | * Converts `Value[]` array to map of string values. 126 | * `Value.type` is ignored, all values are returned as string. 127 | * 128 | * 129 | * sample input: 130 | * ```javascript 131 | * [{ 132 | * name: 'address', 133 | * type: 'ByStr20', 134 | * value: '0xbadbeef', 135 | * }, { 136 | * name: 'balance', 137 | * type: 'UInt28', 138 | * value: '100000000', 139 | * }] 140 | * ``` 141 | * 142 | * output: 143 | * ```javascript 144 | * { 145 | * address: '0xbadbeef', 146 | * balance: '100000000', 147 | * } 148 | * ``` 149 | * 150 | * @param params parameters in `Value[]` array representation 151 | * @returns mapped object representation - refer to sample output 152 | */ 153 | export const contractInitToMap = (params: Value[]): { [index: string]: any } => { 154 | const output: { [index: string]: any } = {} 155 | for (const set of params) { 156 | output[set.vname] = set.value 157 | } 158 | return output 159 | } 160 | 161 | /* ARK utils */ 162 | 163 | /** 164 | * Returns the message hash to sign. 165 | * @param msg - the utf-8 message 166 | * @returns - the computed message hahs to sign 167 | */ 168 | export const hashMessage = (msg: string): string => { 169 | return crypto.createHash('sha256').update(Buffer.from(msg, 'utf-8')).digest('hex') 170 | } 171 | 172 | /** 173 | * Returns the message to sign for ARK. 174 | * @param type - the type of message, either 'Execute' or 'Void' 175 | * @param chequeHash - the computed cheque hash for the trade intent 176 | * @returns 177 | */ 178 | export const arkMessage = (type: 'Execute' | 'Void', chequeHash: string) => { 179 | return `Zilliqa Signed Message:\n${type} ARK Cheque 0x${chequeHash}` 180 | } 181 | 182 | export type ArkChequeParams = { 183 | network: Network 184 | side: 'Buy' | 'Sell' 185 | token: { id: string; address: string } 186 | price: { amount: BigNumber; address: string } 187 | feeAmount: BigNumber 188 | expiry: number 189 | nonce: number 190 | } 191 | 192 | /** 193 | * Computes the cheque hash for a trade intent on ARK. 194 | * @param params - trade parameters 195 | * @returns 196 | */ 197 | export const arkChequeHash = (params: ArkChequeParams): string => { 198 | const { network, side, token, price, feeAmount, expiry, nonce } = params 199 | const brokerAddress = fromBech32Address(ARK_CONTRACTS[network]).toLowerCase() 200 | let buffer = brokerAddress.replace('0x', '') 201 | buffer += sha256(strToHex(`${brokerAddress}.${side}`)) 202 | buffer += sha256(serializeNFT(brokerAddress, token)) 203 | buffer += sha256(serializePrice(brokerAddress, price)) 204 | buffer += sha256(serializeUint128(side === 'Buy' ? 0 : feeAmount)) 205 | buffer += sha256(strToHex(expiry.toString())) // BNum is serialized as a String 206 | buffer += sha256(serializeUint128(nonce)) 207 | return sha256(buffer) 208 | } 209 | 210 | const serializeNFT = (brokerAddress: string, token: { id: string; address: string }): string => { 211 | let buffer = strToHex(`${brokerAddress}.NFT`) 212 | buffer += token.address.replace('0x', '').toLowerCase() 213 | buffer += serializeUint256(token.id) 214 | return buffer 215 | } 216 | 217 | const serializePrice = (brokerAddress: string, price: { amount: BigNumber; address: string }): string => { 218 | let buffer = strToHex(`${brokerAddress}.Coins`) 219 | if (price.address === ZIL_HASH) { 220 | buffer += strToHex(`${brokerAddress}.Zil`) 221 | } else { 222 | buffer += strToHex(`${brokerAddress}.Token`) 223 | buffer += price.address.replace('0x', '').toLowerCase() 224 | } 225 | buffer += serializeUint128(price.amount) 226 | return buffer 227 | } 228 | 229 | const serializeUint128 = (val: BigNumber | number): string => { 230 | return new BN(val.toString()).toBuffer('be', 16).toString('hex') 231 | } 232 | 233 | const serializeUint256 = (val: BigNumber | string): string => { 234 | return new BN(val.toString()).toBuffer('be', 32).toString('hex') 235 | } 236 | 237 | const strToHex = (str: string): string => { 238 | return Array.from(new TextEncoder().encode(str), byte => byte.toString(16).padStart(2, '0')).join('') 239 | } 240 | 241 | const sha256 = (byteHexString: string): string => { 242 | return crypto.createHash('sha256').update(Buffer.from(byteHexString, 'hex')).digest('hex') 243 | } 244 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from 'bignumber.js' 2 | import { sign, getPubKeyFromPrivateKey, getAddressFromPrivateKey } from '@zilliqa-js/crypto' 3 | import { Zilswap, ObservedTx, TxStatus, TxReceipt } from './index' 4 | import { Network, ZIL_HASH } from './constants' 5 | import { arkMessage, arkChequeHash, hashMessage } from './utils' 6 | 7 | const key: string | undefined = process.env.PRIVATE_KEY || undefined 8 | const zilswap = new Zilswap(Network.TestNet, key) 9 | 10 | const test = async () => { 11 | // init 12 | await zilswap.initialize(printResults) 13 | 14 | // get app state 15 | console.log('\ninitial app state:\n') 16 | console.log(JSON.stringify(zilswap.getAppState(), null, 2)) 17 | 18 | try { 19 | // approve token 20 | const tx0 = await zilswap.approveTokenTransferIfRequired('SWTH', await zilswap.toUnitless('SWTH', '100000')) 21 | if (tx0) { 22 | console.log(`\ntx hash: ${tx0.hash}\n`) 23 | await waitForTx() 24 | } 25 | 26 | // add liquidity 27 | const tx1 = await zilswap.addLiquidity('SWTH', await zilswap.toUnitless('ZIL', '10000'), await zilswap.toUnitless('SWTH', '10000')) 28 | console.log(`\ntx hash: ${tx1.hash}\n`) 29 | // await waitForTx() 30 | 31 | // remove liquidity 32 | const pool = zilswap.getPool('SWTH') 33 | const remove25Percent = pool!.userContribution.dividedToIntegerBy(4).toString() 34 | const tx2 = await zilswap.removeLiquidity('SWTH', remove25Percent) 35 | console.log(`\ntx hash: ${tx2.hash}\n`) 36 | // await waitForTx() 37 | 38 | // constants 39 | const someSWTH = await zilswap.toUnitless('SWTH', '0.1') 40 | const someZIL = await zilswap.toUnitless('ZIL', '0.1') 41 | 42 | // get expected rates for exact input 43 | const r1 = await zilswap.getRatesForInput('SWTH', 'ZIL', someSWTH) 44 | console.log('\n0.1 SWTH -> ZIL\n') 45 | console.log(JSON.stringify(r1, null, 2)) 46 | 47 | // swap exact zrc2 to zil 48 | const tx3 = await zilswap.swapWithExactInput('SWTH', 'ZIL', someSWTH) 49 | console.log(`\ntx hash: ${tx3.hash}\n`) 50 | // await waitForTx() 51 | 52 | // get expected rates for exact input 53 | const r2 = await zilswap.getRatesForInput('ZIL', 'SWTH', someZIL) 54 | console.log('\n0.1 ZIL -> SWTH\n') 55 | console.log(JSON.stringify(r2, null, 2)) 56 | 57 | // swap exact zil to zrc2 58 | const tx4 = await zilswap.swapWithExactInput('ZIL', 'SWTH', someZIL) 59 | console.log(`\ntx hash: ${tx4.hash}\n`) 60 | // await waitForTx() 61 | 62 | // get expected rates for exact output 63 | const r3 = await zilswap.getRatesForOutput('SWTH', 'ZIL', someZIL) 64 | console.log('\nSWTH -> 0.1 ZIL\n') 65 | console.log(JSON.stringify(r3, null, 2)) 66 | 67 | // swap zrc2 to exact zil 68 | const tx5 = await zilswap.swapWithExactOutput('SWTH', 'ZIL', someZIL) 69 | console.log(`\ntx hash: ${tx5.hash}\n`) 70 | await waitForTx() 71 | 72 | // get expected rates for exact output 73 | const r4 = await zilswap.getRatesForOutput('ZIL', 'SWTH', someSWTH) 74 | console.log('\nZIL -> 0.1 SWTH\n') 75 | console.log(JSON.stringify(r4, null, 2)) 76 | 77 | // swap zil to exact zrc2 78 | const tx6 = await zilswap.swapWithExactOutput('ZIL', 'SWTH', someSWTH) 79 | console.log(`\ntx hash: ${tx6.hash}\n`) 80 | await waitForTx() 81 | } finally { 82 | await zilswap.teardown() 83 | } 84 | } 85 | 86 | const test2 = async () => { 87 | // init 88 | await zilswap.initialize(printResults) 89 | 90 | // get app state 91 | console.log('\ninitial app state:\n') 92 | console.log(JSON.stringify(zilswap.getAppState(), null, 2)) 93 | 94 | try { 95 | // approve token 96 | const tx0 = await zilswap.approveTokenTransferIfRequired('XSGD', await zilswap.toUnitless('XSGD', '100000')) 97 | if (tx0) { 98 | console.log(`\ntx hash: ${tx0.hash}\n`) 99 | await waitForTx() 100 | } 101 | 102 | // add liquidity 103 | const tx1 = await zilswap.addLiquidity('XSGD', await zilswap.toUnitless('ZIL', '100000'), await zilswap.toUnitless('XSGD', '10000')) 104 | console.log(`\ntx hash: ${tx1.hash}\n`) 105 | await waitForTx() 106 | 107 | // remove liquidity 108 | const pool = zilswap.getPool('XSGD') 109 | const remove25Percent = pool!.userContribution.dividedToIntegerBy(4).toString() 110 | const tx2 = await zilswap.removeLiquidity('XSGD', remove25Percent) 111 | console.log(`\ntx hash: ${tx2.hash}\n`) 112 | await waitForTx() 113 | 114 | // constants 115 | const someSWTH = await zilswap.toUnitless('SWTH', '0.1') 116 | const someXSGD = await zilswap.toUnitless('XSGD', '0.1') 117 | 118 | // get expected rates for exact input 119 | const r1 = await zilswap.getRatesForInput('SWTH', 'XSGD', someSWTH) 120 | console.log('\n0.1 SWTH -> XSGD\n') 121 | console.log(JSON.stringify(r1, null, 2)) 122 | 123 | // swap exact zrc2 to zrc2 124 | const tx3 = await zilswap.swapWithExactInput('SWTH', 'XSGD', someSWTH) 125 | console.log(`\ntx hash: ${tx3.hash}\n`) 126 | await waitForTx() 127 | 128 | // get expected rates for exact input 129 | const r2 = await zilswap.getRatesForInput('XSGD', 'SWTH', someXSGD) 130 | console.log('\n0.1 XSGD -> SWTH\n') 131 | console.log(JSON.stringify(r2, null, 2)) 132 | 133 | // swap exact zrc2 to zrc2 134 | const tx4 = await zilswap.swapWithExactInput('XSGD', 'SWTH', someXSGD) 135 | console.log(`\ntx hash: ${tx4.hash}\n`) 136 | await waitForTx() 137 | 138 | // get expected rates for exact output 139 | const r3 = await zilswap.getRatesForOutput('SWTH', 'XSGD', someXSGD) 140 | console.log('\nSWTH -> 0.1 XSGD\n') 141 | console.log(JSON.stringify(r3, null, 2)) 142 | 143 | // swap zrc2 to exact zrc2 144 | const tx5 = await zilswap.swapWithExactOutput('SWTH', 'XSGD', someXSGD) 145 | console.log(`\ntx hash: ${tx5.hash}\n`) 146 | await waitForTx() 147 | 148 | // get expected rates for exact output 149 | const r4 = await zilswap.getRatesForOutput('XSGD', 'SWTH', someSWTH) 150 | console.log('\nXSGD -> 0.1 SWTH\n') 151 | console.log(JSON.stringify(r4, null, 2)) 152 | 153 | // swap zrc2 to exact zrc2 154 | const tx6 = await zilswap.swapWithExactOutput('XSGD', 'SWTH', someSWTH) 155 | console.log(`\ntx hash: ${tx6.hash}\n`) 156 | await waitForTx() 157 | } finally { 158 | await zilswap.teardown() 159 | } 160 | } 161 | 162 | const test3 = () => { 163 | const msg = arkMessage( 164 | 'Execute', 165 | arkChequeHash({ 166 | network: Network.TestNet, 167 | side: 'Buy', 168 | token: { id: '206', address: '0xc948942f55ef05a95a46bb58ee9b0a67b0f871fa' }, 169 | price: { amount: new BigNumber(10000), address: ZIL_HASH }, 170 | feeAmount: new BigNumber(250), 171 | expiry: 100, 172 | nonce: 0, 173 | }) 174 | ) 175 | console.log('Message:', msg) 176 | const address = getAddressFromPrivateKey(key!) 177 | console.log('Address:', address) 178 | const publicKey = getPubKeyFromPrivateKey(key!) 179 | console.log('Public Key:', publicKey) 180 | const hash = hashMessage(msg) 181 | console.log('Message Hash:', hash) 182 | const signature = sign(Buffer.from(hash, 'hex'), key!, publicKey) 183 | console.log('Signature:', signature) 184 | } 185 | 186 | const printResults = (tx: ObservedTx, status: TxStatus, receipt?: TxReceipt) => { 187 | if (!receipt) { 188 | console.error(`\ntx ${tx.hash} failed with ${status}!\n`) 189 | } else if (status !== 'confirmed') { 190 | console.error(`\ntx ${tx.hash} failed with ${status}!\ntx receipt: \n`) 191 | console.error(JSON.stringify(receipt, null, 2)) 192 | } else { 193 | console.log(`\ntx ${tx.hash} confirmed.\napp state:\n`) 194 | console.log(JSON.stringify(zilswap.getAppState(), null, 2)) 195 | } 196 | } 197 | 198 | const waitForTx = async () => { 199 | return new Promise(resolve => { 200 | const check = async () => { 201 | if ((await zilswap.getObservedTxs()).length === 0) { 202 | resolve() 203 | } else { 204 | setTimeout(check, 100) 205 | } 206 | } 207 | check() 208 | }) 209 | } 210 | 211 | ;(async () => { 212 | console.log('test starting..') 213 | try { 214 | // await test() 215 | // await test2() 216 | test3() 217 | console.log('test done!') 218 | } catch (err) { 219 | console.error(err) 220 | console.log('test failed!') 221 | } 222 | })() 223 | -------------------------------------------------------------------------------- /src/zilo.ts: -------------------------------------------------------------------------------- 1 | import { Contract, Value } from '@zilliqa-js/contract' 2 | import { BN, Long } from '@zilliqa-js/util' 3 | import { BigNumber } from 'bignumber.js' 4 | import { ObservedTx, TxParams, Zilswap } from './index' 5 | import { ILOState } from './constants' 6 | import { contractInitToMap, unitlessBigNumber } from './utils' 7 | 8 | interface ADTValue { 9 | constructor: string 10 | argtypes: string[] 11 | arguments: Value[] 12 | } 13 | 14 | export type OnStateUpdate = (appState: ZiloAppState) => void 15 | 16 | export type ZiloContractState = { 17 | initialized: ADTValue 18 | contributions: { [byStr20Address: string]: BigNumber } 19 | total_contributions: string 20 | balances?: { [byStr20Address: string]: BigNumber } 21 | discount_whitelist?: { 22 | [byStr20Address: string]: string; 23 | } 24 | } 25 | 26 | export type ZiloContractInit = { 27 | zwap_address: string 28 | token_address: string 29 | token_amount: BigNumber 30 | target_zil_amount: BigNumber 31 | target_zwap_amount: BigNumber 32 | minimum_zil_amount: BigNumber 33 | liquidity_zil_amount: BigNumber 34 | receiver_address: string 35 | liquidity_address: string 36 | start_block: number 37 | end_block: number 38 | _scilla_version: string 39 | _creation_block: string 40 | _this_address: string 41 | discount_bps?: number 42 | } 43 | 44 | export type ZiloAppState = { 45 | contractState: ZiloContractState 46 | state: ILOState 47 | claimable: boolean 48 | contributed: boolean 49 | currentNonce: number | null 50 | currentUser: string | null 51 | userContribution: BigNumber 52 | contractInit: ZiloContractInit | null 53 | } 54 | 55 | /** 56 | * Zilo class to represent an instance of a ZilSwap Initial Launch Offering. 57 | * 58 | * Usage: 59 | * ``` 60 | * const zilswap = new Zilswap(Network.TestNet) 61 | * await zilswap.initialize() 62 | * const zilo = await zilswap.registerZilo(ZILO_ADDRESS, ziloStateObserver) 63 | * 64 | * const ziloState = zilo.getZiloState() 65 | * 66 | * if (ziloState.state === ILOState.Active) { 67 | * const amount = new BigNumber(1).shiftedBy(ZIL_DECIMALS).toString(10) 68 | * const tx = await zilo.contribute(amount) 69 | * 70 | * console.log("distribute TX sent", tx.hash) 71 | * } else { 72 | * console.log("ZILO not yet active") 73 | * } 74 | * ``` 75 | */ 76 | export class Zilo { 77 | private zilswap: Zilswap 78 | private contract: Contract 79 | private appState?: ZiloAppState 80 | 81 | private stateObserver?: OnStateUpdate 82 | 83 | constructor(zilswap: Zilswap, address: string) { 84 | this.zilswap = zilswap 85 | this.contract = zilswap.getContract(address) 86 | } 87 | 88 | public async initialize(observer?: OnStateUpdate) { 89 | this.updateObserver(observer) 90 | await this.updateZiloState() 91 | } 92 | 93 | public updateObserver(observer?: OnStateUpdate) { 94 | this.stateObserver = observer 95 | } 96 | 97 | private async fetchContractInit(): Promise { 98 | const result = await this.zilswap.fetchContractInit(this.contract) 99 | if (!result) return 100 | 101 | const rawInit = contractInitToMap(result) 102 | 103 | return { 104 | ...rawInit, 105 | 106 | token_amount: new BigNumber(rawInit.token_amount), 107 | target_zil_amount: new BigNumber(rawInit.target_zil_amount), 108 | target_zwap_amount: new BigNumber(rawInit.target_zwap_amount), 109 | minimum_zil_amount: new BigNumber(rawInit.minimum_zil_amount), 110 | liquidity_zil_amount: new BigNumber(rawInit.liquidity_zil_amount), 111 | 112 | start_block: parseInt(rawInit.start_block, 10), 113 | end_block: parseInt(rawInit.end_block, 10), 114 | } as ZiloContractInit 115 | } 116 | 117 | private async fetchContractState(): Promise { 118 | const result = await this.contract.getState() 119 | 120 | const contributions: { [index: string]: BigNumber } = {} 121 | for (const byStr20Address of Object.keys(result.contributions)) { 122 | contributions[byStr20Address] = new BigNumber(result.contributions[byStr20Address]) 123 | } 124 | 125 | const balances: { [index: string]: BigNumber } = {} 126 | for (const byStr20Address of Object.keys(result.balances ?? {})) { 127 | balances[byStr20Address] = new BigNumber(result.balances[byStr20Address]) 128 | } 129 | 130 | return { 131 | ...result, 132 | contributions, 133 | ...!!result.balances && { 134 | balances, 135 | }, 136 | } as ZiloContractState 137 | } 138 | 139 | public async updateZiloState() { 140 | const contractState = await this.fetchContractState() 141 | const stateOfContract = await this.checkStatus(contractState) 142 | 143 | const currentUser = this.zilswap.getAppState().currentUser 144 | 145 | const userContribution = contractState.contributions[currentUser || ''] ?? new BigNumber(0) 146 | const claimable = stateOfContract === ILOState.Completed && new BigNumber(userContribution).isPositive() 147 | const contributed = userContribution.gt(0) 148 | let contractInit = this.appState?.contractInit 149 | 150 | if (!contractInit) { 151 | contractInit = await this.fetchContractInit() 152 | if (!contractInit) { 153 | console.error(`Could not fetch contract init for Zilo ${this.contract.address}`) 154 | return 155 | } 156 | } 157 | 158 | const newState = { 159 | contractState, 160 | claimable, 161 | contributed, 162 | currentNonce: this.appState?.currentNonce || 0, 163 | currentUser, 164 | state: stateOfContract, 165 | userContribution, 166 | contractInit, 167 | } 168 | 169 | this.appState = newState 170 | this.stateObserver?.(newState) 171 | } 172 | 173 | public async updateBlockHeight(height?: number) { 174 | if (!this.appState?.contractInit) { 175 | // not initialized, ignore update. 176 | return 177 | } 178 | 179 | if (typeof height === 'undefined') { 180 | const response = await this.zilswap.zilliqa.blockchain.getNumTxBlocks() 181 | height = parseInt(response.result!, 10) 182 | } 183 | 184 | const contractInit = this.appState.contractInit 185 | if (height === contractInit.start_block || height === contractInit.end_block) { 186 | // trigger update if start/end block is current height 187 | await this.updateZiloState() 188 | } 189 | } 190 | 191 | public getZiloState(): ZiloAppState { 192 | if (!this.appState) { 193 | throw new Error('Zilo app state not loaded, call #initialize first.') 194 | } 195 | return this.appState 196 | } 197 | 198 | /** 199 | * Checks the state of the current contract 200 | * ILOState.Uninitialized = Contract deployed but not initialized 201 | * ILOState.Pending = Contract initialized not stated (current block < start block) 202 | * ILOState.Active = Contract started 203 | * ILOState.Failed = Contract ended but target amount not reached 204 | * ILOState.Completed = Contract ended and target amount fufilled 205 | * 206 | * @param contractState 207 | * @returns returns the current ILOState 208 | */ 209 | private async checkStatus(contractState: ZiloContractState): Promise { 210 | const contractInit = await this.fetchContractInit() 211 | 212 | if (!contractInit || contractState.initialized.constructor !== 'True') { 213 | return ILOState.Uninitialized 214 | } 215 | 216 | const currentBlock = this.zilswap.getCurrentBlock() 217 | 218 | if (currentBlock < contractInit.start_block) { 219 | return ILOState.Pending 220 | } 221 | 222 | if (currentBlock < contractInit.end_block) { 223 | return ILOState.Active 224 | } 225 | 226 | if (new BigNumber(contractInit.minimum_zil_amount).gt(new BigNumber(contractState.total_contributions))) { 227 | return ILOState.Failed 228 | } else { 229 | return ILOState.Completed 230 | } 231 | } 232 | 233 | /** 234 | * Execute claim function if user contributed 235 | */ 236 | public async claim(): Promise { 237 | // Check init 238 | this.zilswap.checkAppLoadedWithUser() 239 | 240 | // check if current state is claimable 241 | if (this.appState?.state !== ILOState.Completed && this.appState?.state !== ILOState.Failed) { 242 | throw new Error('Not yet claimable/refundable') 243 | } 244 | 245 | // no contribution 246 | if (!this.appState?.contributed) { 247 | throw new Error('User did not contribute') 248 | } 249 | 250 | const claimTxn = await this.zilswap.callContract( 251 | this.contract, 252 | 'Claim', 253 | [], 254 | { amount: new BN(0), ...this.zilswap.txParams(), gasLimit: Long.fromNumber(20000) }, 255 | true 256 | ) 257 | 258 | if (claimTxn.isRejected()) { 259 | throw new Error('Claim transaction was rejected.') 260 | } 261 | 262 | const deadline = this.zilswap.deadlineBlock() 263 | 264 | const observeTxn = { 265 | hash: claimTxn.id!, 266 | deadline, 267 | } 268 | await this.zilswap.observeTx(observeTxn) 269 | 270 | return observeTxn 271 | } 272 | 273 | public async complete(): Promise { 274 | this.zilswap.checkAppLoadedWithUser() 275 | 276 | const completeTxn = await this.zilswap.callContract( 277 | this.contract, 278 | 'Complete', 279 | [], 280 | { amount: new BN(0), ...this.zilswap.txParams() }, 281 | true 282 | ) 283 | 284 | if (completeTxn.isRejected()) { 285 | throw new Error('Complete transaction was rejected.') 286 | } 287 | 288 | const deadline = this.zilswap.deadlineBlock() 289 | 290 | const observeTxn = { 291 | hash: completeTxn.id!, 292 | deadline, 293 | } 294 | await this.zilswap.observeTx(observeTxn) 295 | 296 | return observeTxn 297 | } 298 | 299 | /** 300 | * Contribute to the ILO, may need to increase token allowance before proceeding 301 | * 302 | * @param amountToContributeStr is the exact amount of ZIL to be contribute as a unitless string (without decimals). 303 | */ 304 | public async contribute(amountToContributeStr: string, opts?: TxParams): Promise { 305 | this.zilswap.checkAppLoadedWithUser() 306 | 307 | // Check init 308 | const amountToContribute = unitlessBigNumber(amountToContributeStr) 309 | 310 | const contributeTxn = await this.zilswap.callContract( 311 | this.contract, 312 | 'Contribute', 313 | [], 314 | { 315 | amount: new BN(amountToContribute.toString()), 316 | ...this.zilswap.txParams(), 317 | gasLimit: Long.fromNumber(10000), 318 | ...opts 319 | }, 320 | true 321 | ) 322 | 323 | if (contributeTxn.isRejected()) { 324 | throw new Error('Contribute transaction was rejected.') 325 | } 326 | 327 | const deadline = this.zilswap.deadlineBlock() 328 | 329 | const observeTxn = { 330 | hash: contributeTxn.id!, 331 | deadline, 332 | } 333 | await this.zilswap.observeTx(observeTxn) 334 | 335 | return observeTxn 336 | } 337 | } 338 | -------------------------------------------------------------------------------- /docs/classes/index.zilswap.md: -------------------------------------------------------------------------------- 1 | [zilswap-sdk](../README.md) / [Exports](../modules.md) / [index](../modules/index.md) / Zilswap 2 | 3 | # Class: Zilswap 4 | 5 | [zilswap](../modules/index.md) 6 | 7 | ## Table of contents 8 | 9 | ### Constructors 10 | 11 | - [constructor](index.zilswap.md#constructor) 12 | 13 | ### Properties 14 | 15 | - [\_txParams](index.zilswap.md#_txparams) 16 | - [contract](index.zilswap.md#contract) 17 | - [contractAddress](index.zilswap.md#contractaddress) 18 | - [contractHash](index.zilswap.md#contracthash) 19 | - [network](index.zilswap.md#network) 20 | - [zilliqa](index.zilswap.md#zilliqa) 21 | - [zilos](index.zilswap.md#zilos) 22 | 23 | ### Methods 24 | 25 | - [addLiquidity](index.zilswap.md#addliquidity) 26 | - [addToken](index.zilswap.md#addtoken) 27 | - [approveTokenTransferIfRequired](index.zilswap.md#approvetokentransferifrequired) 28 | - [callContract](index.zilswap.md#callcontract) 29 | - [checkAppLoadedWithUser](index.zilswap.md#checkapploadedwithuser) 30 | - [deadlineBlock](index.zilswap.md#deadlineblock) 31 | - [deregisterZilo](index.zilswap.md#deregisterzilo) 32 | - [fetchContractInit](index.zilswap.md#fetchcontractinit) 33 | - [getAppState](index.zilswap.md#getappstate) 34 | - [getContract](index.zilswap.md#getcontract) 35 | - [getCurrentBlock](index.zilswap.md#getcurrentblock) 36 | - [getObservedTxs](index.zilswap.md#getobservedtxs) 37 | - [getPool](index.zilswap.md#getpool) 38 | - [getRatesForInput](index.zilswap.md#getratesforinput) 39 | - [getRatesForOutput](index.zilswap.md#getratesforoutput) 40 | - [initialize](index.zilswap.md#initialize) 41 | - [observeTx](index.zilswap.md#observetx) 42 | - [registerZilo](index.zilswap.md#registerzilo) 43 | - [removeLiquidity](index.zilswap.md#removeliquidity) 44 | - [setDeadlineBlocks](index.zilswap.md#setdeadlineblocks) 45 | - [swapWithExactInput](index.zilswap.md#swapwithexactinput) 46 | - [swapWithExactOutput](index.zilswap.md#swapwithexactoutput) 47 | - [teardown](index.zilswap.md#teardown) 48 | - [toUnit](index.zilswap.md#tounit) 49 | - [toUnitless](index.zilswap.md#tounitless) 50 | - [txParams](index.zilswap.md#txparams) 51 | 52 | ## Constructors 53 | 54 | ### constructor 55 | 56 | • **new Zilswap**(`network`, `walletProviderOrKey?`, `options?`) 57 | 58 | Creates the Zilswap SDK object. {@linkcode initalize} needs to be called after 59 | the object is created to begin watching the blockchain's state. 60 | 61 | #### Parameters 62 | 63 | | Name | Type | Description | 64 | | :------ | :------ | :------ | 65 | | `network` | [Network](../enums/constants.network.md) | the Network to use, either `TestNet` or `MainNet`. | 66 | | `walletProviderOrKey?` | `string` \| `Pick`<`Zilliqa` & { `wallet`: `Wallet` & { `defaultAccount`: { `base16`: `string` ; `bech32`: `string` } ; `net`: `string` } }, ``"provider"`` \| ``"blockchain"`` \| ``"network"`` \| ``"contracts"`` \| ``"transactions"`` \| ``"wallet"``\> | a Provider with Wallet or private key string to be used for signing txns. | 67 | | `options?` | [Options](../modules/index.md#options) | a set of Options that will be used for all txns. | 68 | 69 | #### Defined in 70 | 71 | [index.ts:127](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L127) 72 | 73 | ## Properties 74 | 75 | ### \_txParams 76 | 77 | • `Readonly` **\_txParams**: [TxParams](../modules/index.md#txparams) 78 | 79 | #### Defined in 80 | 81 | [index.ts:123](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L123) 82 | 83 | ___ 84 | 85 | ### contract 86 | 87 | • `Readonly` **contract**: `Contract` 88 | 89 | #### Defined in 90 | 91 | [index.ts:115](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L115) 92 | 93 | ___ 94 | 95 | ### contractAddress 96 | 97 | • `Readonly` **contractAddress**: `string` 98 | 99 | #### Defined in 100 | 101 | [index.ts:116](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L116) 102 | 103 | ___ 104 | 105 | ### contractHash 106 | 107 | • `Readonly` **contractHash**: `string` 108 | 109 | #### Defined in 110 | 111 | [index.ts:117](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L117) 112 | 113 | ___ 114 | 115 | ### network 116 | 117 | • `Readonly` **network**: [Network](../enums/constants.network.md) 118 | 119 | ___ 120 | 121 | ### zilliqa 122 | 123 | • `Readonly` **zilliqa**: `Zilliqa` 124 | 125 | #### Defined in 126 | 127 | [index.ts:96](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L96) 128 | 129 | ___ 130 | 131 | ### zilos 132 | 133 | • `Readonly` **zilos**: `Object` 134 | 135 | #### Index signature 136 | 137 | ▪ [address: `string`]: [Zilo](zilo.zilo-1.md) 138 | 139 | #### Defined in 140 | 141 | [index.ts:120](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L120) 142 | 143 | ## Methods 144 | 145 | ### addLiquidity 146 | 147 | ▸ **addLiquidity**(`tokenID`, `zilsToAddStr`, `tokensToAddStr`, `maxExchangeRateChange?`): `Promise`<[ObservedTx](../modules/index.md#observedtx)\> 148 | 149 | Adds liquidity to the pool with the given `tokenID`. The given `zilsToAddHuman` represents the exact quantity of ZIL 150 | that will be contributed, while the given `tokensToAddHuman` represents the target quantity of ZRC-2 tokens to be 151 | contributed. 152 | 153 | To ensure the liquidity contributor does not lose value to arbitrage, the target token amount should be strictly 154 | derived from the current exchange rate that can be found using [`getPool`](index.zilswap.md#getpool). 155 | 156 | The maximum fluctuation in exchange rate from the given parameters can be controlled through `maxExchangeRateChange`, 157 | to protect against changes in pool reserves between the txn submission and txn confirmation on the Zilliqa blockchain. 158 | 159 | If the pool has no liquidity yet, the token amount given will be the exact quantity of tokens that will be contributed, 160 | and the `maxExchangeRateChange` is ignored. 161 | 162 | The transaction is added to the list of observedTxs, and the observer will be notified on change in tx status. 163 | 164 | Note that all amounts should be given with decimals in it's human represented form, rather than as a unitless integer. 165 | 166 | #### Parameters 167 | 168 | | Name | Type | Default value | Description | 169 | | :------ | :------ | :------ | :------ | 170 | | `tokenID` | `string` | `undefined` | is the token ID for the pool, which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). | 171 | | `zilsToAddStr` | `string` | `undefined` | is the exact amount of zilliqas to contribute to the pool in ZILs as a unitless string. | 172 | | `tokensToAddStr` | `string` | `undefined` | is the target amount of tokens to contribute to the pool as a unitless string. | 173 | | `maxExchangeRateChange` | `number` | 200 | is the maximum allowed exchange rate flucuation given in [basis points](https://www.investopedia.com/terms/b/basispoint.asp). Defaults to 200 = 2.00% if not provided. | 174 | 175 | #### Returns 176 | 177 | `Promise`<[ObservedTx](../modules/index.md#observedtx)\> 178 | 179 | #### Defined in 180 | 181 | [index.ts:534](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L534) 182 | 183 | ___ 184 | 185 | ### addToken 186 | 187 | ▸ **addToken**(`tokenAddress`): `Promise` 188 | 189 | Adds a token which is not already loaded by the default tokens file to the SDK. 190 | 191 | #### Parameters 192 | 193 | | Name | Type | Description | 194 | | :------ | :------ | :------ | 195 | | `tokenAddress` | `string` | is the token address in base16 (0x...) or bech32 (zil...) form. | 196 | 197 | #### Returns 198 | 199 | `Promise` 200 | 201 | true if the token could be found, or false otherwise. 202 | 203 | #### Defined in 204 | 205 | [index.ts:415](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L415) 206 | 207 | ___ 208 | 209 | ### approveTokenTransferIfRequired 210 | 211 | ▸ **approveTokenTransferIfRequired**(`tokenID`, `amountStrOrBN`, `spenderHash?`): `Promise`<``null`` \| [ObservedTx](../modules/index.md#observedtx)\> 212 | 213 | Approves allowing the Zilswap contract to transfer ZRC-2 token with `tokenID`, if the current 214 | approved allowance is less than `amount`. If the allowance is sufficient, this method is a no-op. 215 | 216 | The approval is done by calling `IncreaseAllowance` with the allowance amount as the entire 217 | token supply. This is done so that the approval needs to only be done once per token contract, 218 | reducing the number of approval transactions required for users conducting multiple swaps. 219 | 220 | Non-custodial control of the token is ensured by the Zilswap contract itself, which does not 221 | allow for the transfer of tokens unless explicitly invoked by the sender. 222 | 223 | The transaction is added to the list of observedTxs, and the observer will be notified on 224 | a confirmation or rejection event. The transation will be assumed to be expired after the default 225 | deadline buffer, even though there is no deadline block for this transaction. 226 | 227 | #### Parameters 228 | 229 | | Name | Type | Description | 230 | | :------ | :------ | :------ | 231 | | `tokenID` | `string` | is the token ID for the pool, which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). | 232 | | `amountStrOrBN` | `string` \| `BigNumber` | is the required allowance amount the Zilswap contract requires, below which the `IncreaseAllowance` transition is invoked, as a unitless string or BigNumber. | 233 | | `spenderHash` | `string` | (optional) is the spender contract address, defaults to the ZilSwap contract address. | 234 | 235 | #### Returns 236 | 237 | `Promise`<``null`` \| [ObservedTx](../modules/index.md#observedtx)\> 238 | 239 | an ObservedTx if IncreaseAllowance was called, null if not. 240 | 241 | #### Defined in 242 | 243 | [index.ts:451](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L451) 244 | 245 | ___ 246 | 247 | ### callContract 248 | 249 | ▸ **callContract**(`contract`, `transition`, `args`, `params`, `toDs?`): `Promise` 250 | 251 | #### Parameters 252 | 253 | | Name | Type | 254 | | :------ | :------ | 255 | | `contract` | `Contract` | 256 | | `transition` | `string` | 257 | | `args` | `Value`[] | 258 | | `params` | `Pick` | 259 | | `toDs?` | `boolean` | 260 | 261 | #### Returns 262 | 263 | `Promise` 264 | 265 | #### Defined in 266 | 267 | [index.ts:1157](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L1157) 268 | 269 | ___ 270 | 271 | ### checkAppLoadedWithUser 272 | 273 | ▸ **checkAppLoadedWithUser**(): `void` 274 | 275 | #### Returns 276 | 277 | `void` 278 | 279 | #### Defined in 280 | 281 | [index.ts:1546](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L1546) 282 | 283 | ___ 284 | 285 | ### deadlineBlock 286 | 287 | ▸ **deadlineBlock**(): `number` 288 | 289 | #### Returns 290 | 291 | `number` 292 | 293 | #### Defined in 294 | 295 | [index.ts:1579](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L1579) 296 | 297 | ___ 298 | 299 | ### deregisterZilo 300 | 301 | ▸ **deregisterZilo**(`address`): `void` 302 | 303 | Deregisters an existing Zilo instance. Does nothing if provided 304 | address is not already registered. 305 | 306 | #### Parameters 307 | 308 | | Name | Type | Description | 309 | | :------ | :------ | :------ | 310 | | `address` | `string` | is the Zilo contract address which can be given by either hash (0x...) or bech32 address (zil...). | 311 | 312 | #### Returns 313 | 314 | `void` 315 | 316 | #### Defined in 317 | 318 | [index.ts:227](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L227) 319 | 320 | ___ 321 | 322 | ### fetchContractInit 323 | 324 | ▸ **fetchContractInit**(`contract`): `Promise` 325 | 326 | #### Parameters 327 | 328 | | Name | Type | 329 | | :------ | :------ | 330 | | `contract` | `Contract` | 331 | 332 | #### Returns 333 | 334 | `Promise` 335 | 336 | #### Defined in 337 | 338 | [index.ts:1454](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L1454) 339 | 340 | ___ 341 | 342 | ### getAppState 343 | 344 | ▸ **getAppState**(): [AppState](../modules/index.md#appstate) 345 | 346 | Gets the latest Zilswap app state. 347 | 348 | #### Returns 349 | 350 | [AppState](../modules/index.md#appstate) 351 | 352 | #### Defined in 353 | 354 | [index.ts:261](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L261) 355 | 356 | ___ 357 | 358 | ### getContract 359 | 360 | ▸ **getContract**(`address`): `Contract` 361 | 362 | Gets the contract with the given address that can be called by the default account. 363 | 364 | #### Parameters 365 | 366 | | Name | Type | 367 | | :------ | :------ | 368 | | `address` | `string` | 369 | 370 | #### Returns 371 | 372 | `Contract` 373 | 374 | #### Defined in 375 | 376 | [index.ts:271](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L271) 377 | 378 | ___ 379 | 380 | ### getCurrentBlock 381 | 382 | ▸ **getCurrentBlock**(): `number` 383 | 384 | #### Returns 385 | 386 | `number` 387 | 388 | #### Defined in 389 | 390 | [index.ts:1575](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L1575) 391 | 392 | ___ 393 | 394 | ### getObservedTxs 395 | 396 | ▸ **getObservedTxs**(): `Promise`<[ObservedTx](../modules/index.md#observedtx)[]\> 397 | 398 | Gets the currently observed transactions. 399 | 400 | #### Returns 401 | 402 | `Promise`<[ObservedTx](../modules/index.md#observedtx)[]\> 403 | 404 | #### Defined in 405 | 406 | [index.ts:292](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L292) 407 | 408 | ___ 409 | 410 | ### getPool 411 | 412 | ▸ **getPool**(`tokenID`): ``null`` \| [Pool](../modules/index.md#pool) 413 | 414 | Gets the pool details for the given `tokenID`. 415 | 416 | #### Parameters 417 | 418 | | Name | Type | Description | 419 | | :------ | :------ | :------ | 420 | | `tokenID` | `string` | is the token ID for the pool, which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). | 421 | 422 | #### Returns 423 | 424 | ``null`` \| [Pool](../modules/index.md#pool) 425 | 426 | if pool exists, or `null` otherwise. 427 | 428 | #### Defined in 429 | 430 | [index.ts:282](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L282) 431 | 432 | ___ 433 | 434 | ### getRatesForInput 435 | 436 | ▸ **getRatesForInput**(`tokenInID`, `tokenOutID`, `tokenInAmountStr`): [Rates](../modules/index.md#rates) 437 | 438 | Gets the expected output amount and slippage for a particular set of ZRC-2 or ZIL tokens at the given input amount. 439 | 440 | #### Parameters 441 | 442 | | Name | Type | Description | 443 | | :------ | :------ | :------ | 444 | | `tokenInID` | `string` | is the token ID to be sent to Zilswap (sold), which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. | 445 | | `tokenOutID` | `string` | is the token ID to be taken from Zilswap (bought), which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. | 446 | | `tokenInAmountStr` | `string` | is the exact amount of tokens to be sent to Zilswap as a unitless representable string (without decimals). | 447 | 448 | #### Returns 449 | 450 | [Rates](../modules/index.md#rates) 451 | 452 | #### Defined in 453 | 454 | [index.ts:342](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L342) 455 | 456 | ___ 457 | 458 | ### getRatesForOutput 459 | 460 | ▸ **getRatesForOutput**(`tokenInID`, `tokenOutID`, `tokenOutAmountStr`): [Rates](../modules/index.md#rates) 461 | 462 | Gets the expected input amount and slippage for a particular set of ZRC-2 or ZIL tokens at the given output amount. 463 | Returns NaN values if the given output amount is larger than the pool reserve. 464 | 465 | #### Parameters 466 | 467 | | Name | Type | Description | 468 | | :------ | :------ | :------ | 469 | | `tokenInID` | `string` | is the token ID to be sent to Zilswap (sold), which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. | 470 | | `tokenOutID` | `string` | is the token ID to be taken from Zilswap (bought), which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. | 471 | | `tokenOutAmountStr` | `string` | is the exact amount of tokens to be received from Zilswap as a unitless representable string (without decimals). | 472 | 473 | #### Returns 474 | 475 | [Rates](../modules/index.md#rates) 476 | 477 | #### Defined in 478 | 479 | [index.ts:364](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L364) 480 | 481 | ___ 482 | 483 | ### initialize 484 | 485 | ▸ **initialize**(`subscription?`, `observeTxs?`): `Promise` 486 | 487 | Intializes the SDK, fetching a cache of the Zilswap contract state and 488 | subscribing to subsequent state changes. You may optionally pass an array 489 | of ObservedTx's to subscribe to status changes on any of those txs. 490 | 491 | #### Parameters 492 | 493 | | Name | Type | Default value | Description | 494 | | :------ | :------ | :------ | :------ | 495 | | `subscription?` | [OnUpdate](../modules/index.md#onupdate) | `undefined` | is the callback function to call when a tx state changes. | 496 | | `observeTxs` | [ObservedTx](../modules/index.md#observedtx)[] | [] | - | 497 | 498 | #### Returns 499 | 500 | `Promise` 501 | 502 | #### Defined in 503 | 504 | [index.ts:173](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L173) 505 | 506 | ___ 507 | 508 | ### observeTx 509 | 510 | ▸ **observeTx**(`observedTx`): `Promise` 511 | 512 | Observes the given transaction until the deadline block. 513 | 514 | Calls the `OnUpdate` callback given during `initialize` with the updated ObservedTx 515 | when a change has been observed. 516 | 517 | #### Parameters 518 | 519 | | Name | Type | Description | 520 | | :------ | :------ | :------ | 521 | | `observedTx` | [ObservedTx](../modules/index.md#observedtx) | is the txn hash of the txn to observe with the deadline block number. | 522 | 523 | #### Returns 524 | 525 | `Promise` 526 | 527 | #### Defined in 528 | 529 | [index.ts:400](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L400) 530 | 531 | ___ 532 | 533 | ### registerZilo 534 | 535 | ▸ **registerZilo**(`address`, `onStateUpdate?`): `Promise`<[Zilo](zilo.zilo-1.md)\> 536 | 537 | Initializes a new Zilo instance and registers it to the ZilSwap SDK, 538 | subscribing to subsequent state changes in the Zilo instance. You may 539 | optionally pass a state observer to subscribe to state changes of this 540 | particular Zilo instance. 541 | 542 | If the Zilo instance is already registered, no new instance will be 543 | created. If a new state observer is provided, it will overwrite the 544 | existing one. 545 | 546 | #### Parameters 547 | 548 | | Name | Type | Description | 549 | | :------ | :------ | :------ | 550 | | `address` | `string` | is the Zilo contract address which can be given by either hash (0x...) or bech32 address (zil...). | 551 | | `onStateUpdate?` | [OnStateUpdate](../modules/zilo.md#onstateupdate) | is the state observer which triggers when state updates | 552 | 553 | #### Returns 554 | 555 | `Promise`<[Zilo](zilo.zilo-1.md)\> 556 | 557 | #### Defined in 558 | 559 | [index.ts:203](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L203) 560 | 561 | ___ 562 | 563 | ### removeLiquidity 564 | 565 | ▸ **removeLiquidity**(`tokenID`, `contributionAmount`, `maxExchangeRateChange?`): `Promise`<[ObservedTx](../modules/index.md#observedtx)\> 566 | 567 | Removes `contributionAmount` worth of liquidity from the pool with the given `tokenID`. 568 | 569 | The current user's contribution can be fetched in [`getPool`](index.zilswap.md#getpool), and the expected returned amounts at the 570 | current prevailing exchange rates can be calculated by prorating the liquidity pool reserves by the fraction of 571 | the user's current contribution against the pool's total contribution. 572 | 573 | The maximum fluctuation in exchange rate from the given parameters can be controlled through `maxExchangeRateChange`, 574 | to protect against changes in pool reserves between the txn submission and txn confirmation on the Zilliqa blockchain. 575 | 576 | The transaction is added to the list of observedTxs, and the observer will be notified on change in tx status. 577 | 578 | #### Parameters 579 | 580 | | Name | Type | Default value | Description | 581 | | :------ | :------ | :------ | :------ | 582 | | `tokenID` | `string` | `undefined` | is the token ID for the pool, which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). | 583 | | `contributionAmount` | `string` | `undefined` | is the exact amount of zilliqas to contribute to the pool in ZILs as a string. | 584 | | `maxExchangeRateChange` | `number` | 200 | is the maximum allowed exchange rate flucuation given in [basis points](https://www.investopedia.com/terms/b/basispoint.asp). Defaults to 200 = 2.00% if not provided. | 585 | 586 | #### Returns 587 | 588 | `Promise`<[ObservedTx](../modules/index.md#observedtx)\> 589 | 590 | #### Defined in 591 | 592 | [index.ts:634](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L634) 593 | 594 | ___ 595 | 596 | ### setDeadlineBlocks 597 | 598 | ▸ **setDeadlineBlocks**(`bufferBlocks`): `void` 599 | 600 | Sets the number of blocks to use as the allowable buffer duration before transactions 601 | are considered invalid. 602 | 603 | When a transaction is signed, the deadline block by adding the buffer blocks to 604 | the latest confirmed block height. 605 | 606 | #### Parameters 607 | 608 | | Name | Type | Description | 609 | | :------ | :------ | :------ | 610 | | `bufferBlocks` | `number` | is the number of blocks to use as buffer for the deadline block. | 611 | 612 | #### Returns 613 | 614 | `void` 615 | 616 | #### Defined in 617 | 618 | [index.ts:385](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L385) 619 | 620 | ___ 621 | 622 | ### swapWithExactInput 623 | 624 | ▸ **swapWithExactInput**(`tokenInID`, `tokenOutID`, `tokenInAmountStr`, `maxAdditionalSlippage?`, `recipientAddress?`): `Promise`<[ObservedTx](../modules/index.md#observedtx)\> 625 | 626 | Swaps ZIL or a ZRC-2 token with `tokenInID` for a corresponding ZIL or ZRC-2 token with `tokenOutID`. 627 | 628 | The exact amount of ZIL or ZRC-2 to be sent in (sold) is `tokenInAmountHuman`. The amount received is determined by the prevailing 629 | exchange rate at the current AppState. The expected amount to be received can be given fetched by getExpectedOutput (NYI). 630 | 631 | The maximum additional slippage incurred due to fluctuations in exchange rate from when the 632 | transaction is signed and when it is processed by the Zilliqa blockchain can be bounded by the 633 | `maxAdditionalSlippage` variable. 634 | 635 | The transaction is added to the list of observedTxs, and the observer will be notified on change in tx status. 636 | 637 | #### Parameters 638 | 639 | | Name | Type | Default value | Description | 640 | | :------ | :------ | :------ | :------ | 641 | | `tokenInID` | `string` | `undefined` | is the token ID to be sent to Zilswap (sold), which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. | 642 | | `tokenOutID` | `string` | `undefined` | is the token ID to be taken from Zilswap (bought), which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. | 643 | | `tokenInAmountStr` | `string` | `undefined` | is the exact amount of tokens to be sent to Zilswap as a unitless string (without decimals). | 644 | | `maxAdditionalSlippage` | `number` | 200 | is the maximum additional slippage (on top of slippage due to constant product formula) that the transition will allow before reverting. | 645 | | `recipientAddress` | ``null`` \| `string` | null | is an optional recipient address for receiving the output of the swap in base16 (0x...) or bech32 (zil...). Defaults to the sender address if `null` or undefined. | 646 | 647 | #### Returns 648 | 649 | `Promise`<[ObservedTx](../modules/index.md#observedtx)\> 650 | 651 | #### Defined in 652 | 653 | [index.ts:735](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L735) 654 | 655 | ___ 656 | 657 | ### swapWithExactOutput 658 | 659 | ▸ **swapWithExactOutput**(`tokenInID`, `tokenOutID`, `tokenOutAmountStr`, `maxAdditionalSlippage?`, `recipientAddress?`): `Promise`<[ObservedTx](../modules/index.md#observedtx)\> 660 | 661 | Swaps ZIL or a ZRC-2 token with `tokenInID` for a corresponding ZIL or ZRC-2 token with `tokenOutID`. 662 | 663 | The exact amount of ZIL or ZRC-2 to be received (bought) is `tokenOutAmountHuman`. The amount sent is determined by the prevailing 664 | exchange rate at the current AppState. The expected amount to be sent can be given fetched by getExpectedInput (NYI). 665 | 666 | The maximum additional slippage incurred due to fluctuations in exchange rate from when the 667 | transaction is signed and when it is processed by the Zilliqa blockchain can be bounded by the 668 | `maxAdditionalSlippage` variable. 669 | 670 | The transaction is added to the list of observedTxs, and the observer will be notified on change in tx status. 671 | 672 | #### Parameters 673 | 674 | | Name | Type | Default value | Description | 675 | | :------ | :------ | :------ | :------ | 676 | | `tokenInID` | `string` | `undefined` | is the token ID to be sent to Zilswap (sold), which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. | 677 | | `tokenOutID` | `string` | `undefined` | is the token ID to be taken from Zilswap (bought), which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. | 678 | | `tokenOutAmountStr` | `string` | `undefined` | is the exact amount of tokens to be received from Zilswap as a unitless string (withoout decimals). | 679 | | `maxAdditionalSlippage` | `number` | 200 | is the maximum additional slippage (on top of slippage due to constant product formula) that the transition will allow before reverting. | 680 | | `recipientAddress` | ``null`` \| `string` | null | is an optional recipient address for receiving the output of the swap in base16 (0x...) or bech32 (zil...). Defaults to the sender address if `null` or undefined. | 681 | 682 | #### Returns 683 | 684 | `Promise`<[ObservedTx](../modules/index.md#observedtx)\> 685 | 686 | #### Defined in 687 | 688 | [index.ts:905](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L905) 689 | 690 | ___ 691 | 692 | ### teardown 693 | 694 | ▸ **teardown**(): `Promise` 695 | 696 | Stops watching the Zilswap contract state. 697 | 698 | #### Returns 699 | 700 | `Promise` 701 | 702 | #### Defined in 703 | 704 | [index.ts:242](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L242) 705 | 706 | ___ 707 | 708 | ### toUnit 709 | 710 | ▸ **toUnit**(`tokenID`, `amountStr`): `string` 711 | 712 | Converts an amount to it's human representation (with decimals based on token contract, or 12 decimals for ZIL) 713 | from it's unitless representation (integer, no decimals). 714 | 715 | #### Parameters 716 | 717 | | Name | Type | Description | 718 | | :------ | :------ | :------ | 719 | | `tokenID` | `string` | is the token ID related to the conversion amount, which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. | 720 | | `amountStr` | `string` | is the unitless amount as a string (e.g. 42000000000000 for 42 ZILs) to be converted. | 721 | 722 | #### Returns 723 | 724 | `string` 725 | 726 | #### Defined in 727 | 728 | [index.ts:324](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L324) 729 | 730 | ___ 731 | 732 | ### toUnitless 733 | 734 | ▸ **toUnitless**(`tokenID`, `amountHuman`): `string` 735 | 736 | Converts an amount to it's unitless representation (integer, no decimals) from it's 737 | human representation (with decimals based on token contract, or 12 decimals for ZIL). 738 | 739 | #### Parameters 740 | 741 | | Name | Type | Description | 742 | | :------ | :------ | :------ | 743 | | `tokenID` | `string` | is the token ID related to the conversion amount, which can be given by either it's symbol (defined in constants.ts), hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. | 744 | | `amountHuman` | `string` | is the amount as a human string (e.g. 4.2 for 4.2 ZILs) to be converted. | 745 | 746 | #### Returns 747 | 748 | `string` 749 | 750 | #### Defined in 751 | 752 | [index.ts:308](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L308) 753 | 754 | ___ 755 | 756 | ### txParams 757 | 758 | ▸ **txParams**(): [TxParams](../modules/index.md#txparams) & { `nonce`: `number` } 759 | 760 | #### Returns 761 | 762 | [TxParams](../modules/index.md#txparams) & { `nonce`: `number` } 763 | 764 | #### Defined in 765 | 766 | [index.ts:1568](https://github.com/Switcheo/zilswap-sdk/blob/67d9128/src/index.ts#L1568) 767 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": 6 | version "1.1.2" 7 | resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" 8 | integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78= 9 | 10 | "@protobufjs/base64@^1.1.2": 11 | version "1.1.2" 12 | resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" 13 | integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== 14 | 15 | "@protobufjs/codegen@^2.0.4": 16 | version "2.0.4" 17 | resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" 18 | integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== 19 | 20 | "@protobufjs/eventemitter@^1.1.0": 21 | version "1.1.0" 22 | resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" 23 | integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A= 24 | 25 | "@protobufjs/fetch@^1.1.0": 26 | version "1.1.0" 27 | resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" 28 | integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU= 29 | dependencies: 30 | "@protobufjs/aspromise" "^1.1.1" 31 | "@protobufjs/inquire" "^1.1.0" 32 | 33 | "@protobufjs/float@^1.0.2": 34 | version "1.0.2" 35 | resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" 36 | integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E= 37 | 38 | "@protobufjs/inquire@^1.1.0": 39 | version "1.1.0" 40 | resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" 41 | integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik= 42 | 43 | "@protobufjs/path@^1.1.2": 44 | version "1.1.2" 45 | resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" 46 | integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0= 47 | 48 | "@protobufjs/pool@^1.1.0": 49 | version "1.1.0" 50 | resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" 51 | integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q= 52 | 53 | "@protobufjs/utf8@^1.1.0": 54 | version "1.1.0" 55 | resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" 56 | integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= 57 | 58 | "@types/bip39@^2.4.0": 59 | version "2.4.2" 60 | resolved "https://registry.yarnpkg.com/@types/bip39/-/bip39-2.4.2.tgz#f5d6617212be496bb998d3969f657f77a10c5287" 61 | integrity sha512-Vo9lqOIRq8uoIzEVrV87ZvcIM0PN9t0K3oYZ/CS61fIYKCBdOIM7mlWzXuRvSXrDtVa1uUO2w1cdfufxTC0bzg== 62 | dependencies: 63 | "@types/node" "*" 64 | 65 | "@types/bn.js@^4.11.3": 66 | version "4.11.6" 67 | resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" 68 | integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== 69 | dependencies: 70 | "@types/node" "*" 71 | 72 | "@types/hdkey@^0.7.0": 73 | version "0.7.1" 74 | resolved "https://registry.yarnpkg.com/@types/hdkey/-/hdkey-0.7.1.tgz#9bc63ebbe96b107b277b65ea7a95442a677d0d61" 75 | integrity sha512-4Kkr06hq+R8a9EzVNqXGOY2x1xA7dhY6qlp6OvaZ+IJy1BCca1Cv126RD9X7CMJoXoLo8WvAizy8gQHpqW6K0Q== 76 | dependencies: 77 | "@types/node" "*" 78 | 79 | "@types/long@^4.0.0", "@types/long@^4.0.1": 80 | version "4.0.1" 81 | resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" 82 | integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== 83 | 84 | "@types/node@*", "@types/node@^13.13.5", "@types/node@^13.7.0": 85 | version "13.13.5" 86 | resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.5.tgz#96ec3b0afafd64a4ccea9107b75bf8489f0e5765" 87 | integrity sha512-3ySmiBYJPqgjiHA7oEaIo2Rzz0HrOZ7yrNO5HWyaE5q0lQ3BppDZ3N53Miz8bw2I7gh1/zir2MGVZBvpb1zq9g== 88 | 89 | "@types/websocket@^1.0.0": 90 | version "1.0.0" 91 | resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.0.tgz#828c794b0a50949ad061aa311af1009934197e4b" 92 | integrity sha512-MLr8hDM8y7vvdAdnoDEP5LotRoYJj7wgT6mWzCUQH/gHqzS4qcnOT/K4dhC0WimWIUiA3Arj9QAJGGKNRiRZKA== 93 | dependencies: 94 | "@types/node" "*" 95 | 96 | "@zilliqa-js/account@2.2.1": 97 | version "2.2.1" 98 | resolved "https://registry.yarnpkg.com/@zilliqa-js/account/-/account-2.2.1.tgz#f12c2ef5219a899bd5c64077fbf0a4b677189ce4" 99 | integrity sha512-egq/S1KyrH8qlmMBKHaAmLU/RLl66JYPDEPe3n97NP/yvrbPTt7sEfgfOwL1IO0hIBLlJPQYIdKtlYHzn22BLw== 100 | dependencies: 101 | "@types/bip39" "^2.4.0" 102 | "@types/hdkey" "^0.7.0" 103 | "@zilliqa-js/core" "2.2.1" 104 | "@zilliqa-js/crypto" "2.2.1" 105 | "@zilliqa-js/proto" "2.2.0" 106 | "@zilliqa-js/util" "2.2.0" 107 | bip39 "^2.5.0" 108 | hdkey "^1.1.0" 109 | 110 | "@zilliqa-js/blockchain@2.2.1": 111 | version "2.2.1" 112 | resolved "https://registry.yarnpkg.com/@zilliqa-js/blockchain/-/blockchain-2.2.1.tgz#bed1811bc5af4ce8cd7f32620a1aa4e368cad975" 113 | integrity sha512-GiUzRAceOgsF9Nk/LzdionZt6QlLMDH72Z4/qt1SQY2vdK0rz9fbjBtQbZjVjfvwvGSjmOBo3KVYPhviJHuGYQ== 114 | dependencies: 115 | "@zilliqa-js/account" "2.2.1" 116 | "@zilliqa-js/contract" "2.2.1" 117 | "@zilliqa-js/core" "2.2.1" 118 | "@zilliqa-js/crypto" "2.2.1" 119 | "@zilliqa-js/util" "2.2.0" 120 | utility-types "^3.4.1" 121 | 122 | "@zilliqa-js/contract@2.2.1": 123 | version "2.2.1" 124 | resolved "https://registry.yarnpkg.com/@zilliqa-js/contract/-/contract-2.2.1.tgz#2b123f0a0ce77f1a20b10a4d2effdffdc260330d" 125 | integrity sha512-DmhElqUbgyUNxwKwKSJq6L8WfxOBVrrQ72crHrnubIgnhN3uNRaS9lZ4oAMAi1o6eSYe94GCBHGOZ5imSYxFrg== 126 | dependencies: 127 | "@zilliqa-js/account" "2.2.1" 128 | "@zilliqa-js/blockchain" "2.2.1" 129 | "@zilliqa-js/core" "2.2.1" 130 | "@zilliqa-js/crypto" "2.2.1" 131 | "@zilliqa-js/util" "2.2.0" 132 | hash.js "^1.1.5" 133 | utility-types "^2.1.0" 134 | 135 | "@zilliqa-js/core@2.2.1": 136 | version "2.2.1" 137 | resolved "https://registry.yarnpkg.com/@zilliqa-js/core/-/core-2.2.1.tgz#c151d1e2cd530f8928236d68835f0ff7faa119b1" 138 | integrity sha512-dEViTcv54waiDckyWROgBcuwDX8iugSKY/Fooa2RynDGHTlb4XvvAxmShTy4+OF1tldhV86cE9nsDW//ICTZPQ== 139 | dependencies: 140 | "@zilliqa-js/crypto" "2.2.1" 141 | "@zilliqa-js/util" "2.2.0" 142 | cross-fetch "^2.2.2" 143 | mitt "^1.1.3" 144 | 145 | "@zilliqa-js/crypto@2.2.1": 146 | version "2.2.1" 147 | resolved "https://registry.yarnpkg.com/@zilliqa-js/crypto/-/crypto-2.2.1.tgz#c1468244f35a9ebf7f0ee27881e0a718c09f8d97" 148 | integrity sha512-80fCuf6Bjpci+mmTfBp9r+umhWbxji8WE4Ii8jz1QtszkWBXLUvXhw6xFv0txgt74ZmUj12Ot1MENALAFEJEDg== 149 | dependencies: 150 | "@zilliqa-js/util" "2.2.0" 151 | aes-js "^3.1.1" 152 | bsert "^0.0.4" 153 | elliptic "^6.5.0" 154 | hash.js "^1.1.5" 155 | hmac-drbg "^1.0.1" 156 | pbkdf2 "^3.0.16" 157 | randombytes "^2.0.6" 158 | scrypt-js "^3.0.1" 159 | scryptsy "^2.1.0" 160 | sodium-native "^3.2.0" 161 | uuid "^3.3.2" 162 | 163 | "@zilliqa-js/proto@2.2.0": 164 | version "2.2.0" 165 | resolved "https://registry.yarnpkg.com/@zilliqa-js/proto/-/proto-2.2.0.tgz#c3fea22daf4a8e385e5f239119765a0d60f18df7" 166 | integrity sha512-0QPNJdvafT0ItPGrqEff7KMYNCT/DkWCn0/x2/UwVoVANy5BHL3WkwDV3y49KthVwdZUotQVzRaweHTs6PIcuA== 167 | dependencies: 168 | protobufjs "^6.8.8" 169 | 170 | "@zilliqa-js/subscriptions@2.2.1": 171 | version "2.2.1" 172 | resolved "https://registry.yarnpkg.com/@zilliqa-js/subscriptions/-/subscriptions-2.2.1.tgz#f334ef896521d3b6d5c87507cee5acf6cfeeb6fd" 173 | integrity sha512-MIz7i1kRCF7TpDzmpOFOhL13xl2CxCfmzpXvaBF1keGcOrqf8o/rgF7YARZ2H5YXobLlGDP5Gjm2qcShkiYfWw== 174 | dependencies: 175 | "@zilliqa-js/core" "2.2.1" 176 | mock-socket "^9.0.2" 177 | websocket "^1.0.28" 178 | 179 | "@zilliqa-js/util@2.2.0": 180 | version "2.2.0" 181 | resolved "https://registry.yarnpkg.com/@zilliqa-js/util/-/util-2.2.0.tgz#6f64adc5494596c93dd0eff566f830b316eba677" 182 | integrity sha512-bzThiraMQKDumhQY0HMsutX28HPgqB+KKqiet8M8QQbCFvQODxAGpuxJX6bZiX+6K6tZUk8yDSW8Ri3dgOdRDg== 183 | dependencies: 184 | "@types/bn.js" "^4.11.3" 185 | "@types/long" "^4.0.0" 186 | bn.js "^4.11.8" 187 | long "^4.0.0" 188 | 189 | "@zilliqa-js/zilliqa@^2.2.0": 190 | version "2.2.1" 191 | resolved "https://registry.yarnpkg.com/@zilliqa-js/zilliqa/-/zilliqa-2.2.1.tgz#7d39c8e8459b050033bd5f77126a9fb0fd59d8f6" 192 | integrity sha512-gN3VnuwSvK7SFlzRiXUg18In9rBHn33iZRfmVrggRqTtwG04Dv4AyiCG37+ieNG5hQHI5O+gRrCIPSVG24/n2w== 193 | dependencies: 194 | "@zilliqa-js/account" "2.2.1" 195 | "@zilliqa-js/blockchain" "2.2.1" 196 | "@zilliqa-js/contract" "2.2.1" 197 | "@zilliqa-js/core" "2.2.1" 198 | "@zilliqa-js/crypto" "2.2.1" 199 | "@zilliqa-js/subscriptions" "2.2.1" 200 | "@zilliqa-js/util" "2.2.0" 201 | 202 | aes-js@^3.1.1: 203 | version "3.1.2" 204 | resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" 205 | integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== 206 | 207 | async-mutex@^0.2.2: 208 | version "0.2.2" 209 | resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.2.2.tgz#3a9de4be23615abce7d52730b4d3a43d9258fe06" 210 | integrity sha512-L1wZNK83y16khj/Fqezy+FfOp5KuywxypF/C2aYfAN3NOMLYdAVKRk3UDklqv+ngX+O+tNSEkPX+FxprxELsMA== 211 | dependencies: 212 | tslib "^1.11.1" 213 | 214 | base-x@^3.0.2: 215 | version "3.0.8" 216 | resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d" 217 | integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA== 218 | dependencies: 219 | safe-buffer "^5.0.1" 220 | 221 | bignumber.js@^9.0.0: 222 | version "9.0.1" 223 | resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" 224 | integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== 225 | 226 | bindings@^1.5.0: 227 | version "1.5.0" 228 | resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" 229 | integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== 230 | dependencies: 231 | file-uri-to-path "1.0.0" 232 | 233 | bip39@^2.5.0: 234 | version "2.6.0" 235 | resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.6.0.tgz#9e3a720b42ec8b3fbe4038f1e445317b6a99321c" 236 | integrity sha512-RrnQRG2EgEoqO24ea+Q/fftuPUZLmrEM3qNhhGsA3PbaXaCW791LTzPuVyx/VprXQcTbPJ3K3UeTna8ZnVl2sg== 237 | dependencies: 238 | create-hash "^1.1.0" 239 | pbkdf2 "^3.0.9" 240 | randombytes "^2.0.1" 241 | safe-buffer "^5.0.1" 242 | unorm "^1.3.3" 243 | 244 | bip66@^1.1.5: 245 | version "1.1.5" 246 | resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" 247 | integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= 248 | dependencies: 249 | safe-buffer "^5.0.1" 250 | 251 | bn.js@^4.11.8, bn.js@^4.11.9: 252 | version "4.12.0" 253 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" 254 | integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== 255 | 256 | bn.js@^5.1.1: 257 | version "5.1.1" 258 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.1.tgz#48efc4031a9c4041b9c99c6941d903463ab62eb5" 259 | integrity sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA== 260 | 261 | brorand@^1.1.0: 262 | version "1.1.0" 263 | resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" 264 | integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= 265 | 266 | browserify-aes@^1.0.6: 267 | version "1.2.0" 268 | resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" 269 | integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== 270 | dependencies: 271 | buffer-xor "^1.0.3" 272 | cipher-base "^1.0.0" 273 | create-hash "^1.1.0" 274 | evp_bytestokey "^1.0.3" 275 | inherits "^2.0.1" 276 | safe-buffer "^5.0.1" 277 | 278 | bs58@^4.0.0: 279 | version "4.0.1" 280 | resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" 281 | integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= 282 | dependencies: 283 | base-x "^3.0.2" 284 | 285 | bs58check@^2.1.2: 286 | version "2.1.2" 287 | resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" 288 | integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== 289 | dependencies: 290 | bs58 "^4.0.0" 291 | create-hash "^1.1.0" 292 | safe-buffer "^5.1.2" 293 | 294 | bsert@^0.0.4: 295 | version "0.0.4" 296 | resolved "https://registry.yarnpkg.com/bsert/-/bsert-0.0.4.tgz#2b3c236357923f0625f948802a5f9b66c0383d0b" 297 | integrity sha512-VReLe1aTaHRmf80YLOHUk8ONQ48SjseZP76GlNIDheD5REYByn/Mm9yrtI0/ZCaFrcfxzgpiw1/hMMCUOSMa3w== 298 | 299 | buffer-xor@^1.0.3: 300 | version "1.0.3" 301 | resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" 302 | integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= 303 | 304 | cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: 305 | version "1.0.4" 306 | resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" 307 | integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== 308 | dependencies: 309 | inherits "^2.0.1" 310 | safe-buffer "^5.0.1" 311 | 312 | create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: 313 | version "1.2.0" 314 | resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" 315 | integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== 316 | dependencies: 317 | cipher-base "^1.0.1" 318 | inherits "^2.0.1" 319 | md5.js "^1.3.4" 320 | ripemd160 "^2.0.1" 321 | sha.js "^2.4.0" 322 | 323 | create-hmac@^1.1.4: 324 | version "1.1.7" 325 | resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" 326 | integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== 327 | dependencies: 328 | cipher-base "^1.0.3" 329 | create-hash "^1.1.0" 330 | inherits "^2.0.1" 331 | ripemd160 "^2.0.0" 332 | safe-buffer "^5.0.1" 333 | sha.js "^2.4.8" 334 | 335 | cross-fetch@^2.2.2: 336 | version "2.2.3" 337 | resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.3.tgz#e8a0b3c54598136e037f8650f8e823ccdfac198e" 338 | integrity sha512-PrWWNH3yL2NYIb/7WF/5vFG3DCQiXDOVf8k3ijatbrtnwNuhMWLC7YF7uqf53tbTFDzHIUD8oITw4Bxt8ST3Nw== 339 | dependencies: 340 | node-fetch "2.1.2" 341 | whatwg-fetch "2.0.4" 342 | 343 | d@1, d@^1.0.1: 344 | version "1.0.1" 345 | resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" 346 | integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== 347 | dependencies: 348 | es5-ext "^0.10.50" 349 | type "^1.0.1" 350 | 351 | debug@^2.2.0: 352 | version "2.6.9" 353 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 354 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 355 | dependencies: 356 | ms "2.0.0" 357 | 358 | drbg.js@^1.0.1: 359 | version "1.0.1" 360 | resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" 361 | integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= 362 | dependencies: 363 | browserify-aes "^1.0.6" 364 | create-hash "^1.1.2" 365 | create-hmac "^1.1.4" 366 | 367 | elliptic@^6.5.0, elliptic@^6.5.2: 368 | version "6.5.4" 369 | resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" 370 | integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== 371 | dependencies: 372 | bn.js "^4.11.9" 373 | brorand "^1.1.0" 374 | hash.js "^1.0.0" 375 | hmac-drbg "^1.0.1" 376 | inherits "^2.0.4" 377 | minimalistic-assert "^1.0.1" 378 | minimalistic-crypto-utils "^1.0.1" 379 | 380 | es5-ext@^0.10.35, es5-ext@^0.10.50: 381 | version "0.10.53" 382 | resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" 383 | integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== 384 | dependencies: 385 | es6-iterator "~2.0.3" 386 | es6-symbol "~3.1.3" 387 | next-tick "~1.0.0" 388 | 389 | es6-iterator@~2.0.3: 390 | version "2.0.3" 391 | resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" 392 | integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= 393 | dependencies: 394 | d "1" 395 | es5-ext "^0.10.35" 396 | es6-symbol "^3.1.1" 397 | 398 | es6-symbol@^3.1.1, es6-symbol@~3.1.3: 399 | version "3.1.3" 400 | resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" 401 | integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== 402 | dependencies: 403 | d "^1.0.1" 404 | ext "^1.1.2" 405 | 406 | evp_bytestokey@^1.0.3: 407 | version "1.0.3" 408 | resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" 409 | integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== 410 | dependencies: 411 | md5.js "^1.3.4" 412 | safe-buffer "^5.1.1" 413 | 414 | ext@^1.1.2: 415 | version "1.4.0" 416 | resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" 417 | integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== 418 | dependencies: 419 | type "^2.0.0" 420 | 421 | file-uri-to-path@1.0.0: 422 | version "1.0.0" 423 | resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" 424 | integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== 425 | 426 | hash-base@^3.0.0: 427 | version "3.1.0" 428 | resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" 429 | integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== 430 | dependencies: 431 | inherits "^2.0.4" 432 | readable-stream "^3.6.0" 433 | safe-buffer "^5.2.0" 434 | 435 | hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.5: 436 | version "1.1.7" 437 | resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" 438 | integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== 439 | dependencies: 440 | inherits "^2.0.3" 441 | minimalistic-assert "^1.0.1" 442 | 443 | hdkey@^1.1.0: 444 | version "1.1.2" 445 | resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.2.tgz#c60f9cf6f90fbf24a8a52ea06893f36a0108cd3e" 446 | integrity sha512-PTQ4VKu0oRnCrYfLp04iQZ7T2Cxz0UsEXYauk2j8eh6PJXCpbXuCFhOmtIFtbET0i3PMWmHN9J11gU8LEgUljQ== 447 | dependencies: 448 | bs58check "^2.1.2" 449 | safe-buffer "^5.1.1" 450 | secp256k1 "^3.0.1" 451 | 452 | hmac-drbg@^1.0.1: 453 | version "1.0.1" 454 | resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" 455 | integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= 456 | dependencies: 457 | hash.js "^1.0.3" 458 | minimalistic-assert "^1.0.0" 459 | minimalistic-crypto-utils "^1.0.1" 460 | 461 | inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: 462 | version "2.0.4" 463 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 464 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 465 | 466 | ini@^1.3.5: 467 | version "1.3.8" 468 | resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" 469 | integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== 470 | 471 | is-typedarray@^1.0.0: 472 | version "1.0.0" 473 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 474 | integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= 475 | 476 | isomorphic-fetch@^3.0.0: 477 | version "3.0.0" 478 | resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4" 479 | integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== 480 | dependencies: 481 | node-fetch "^2.6.1" 482 | whatwg-fetch "^3.4.1" 483 | 484 | long@^4.0.0: 485 | version "4.0.0" 486 | resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" 487 | integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== 488 | 489 | md5.js@^1.3.4: 490 | version "1.3.5" 491 | resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" 492 | integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== 493 | dependencies: 494 | hash-base "^3.0.0" 495 | inherits "^2.0.1" 496 | safe-buffer "^5.1.2" 497 | 498 | minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: 499 | version "1.0.1" 500 | resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" 501 | integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== 502 | 503 | minimalistic-crypto-utils@^1.0.1: 504 | version "1.0.1" 505 | resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" 506 | integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= 507 | 508 | mitt@^1.1.3: 509 | version "1.2.0" 510 | resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.2.0.tgz#cb24e6569c806e31bd4e3995787fe38a04fdf90d" 511 | integrity sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw== 512 | 513 | mock-socket@^9.0.2: 514 | version "9.0.3" 515 | resolved "https://registry.yarnpkg.com/mock-socket/-/mock-socket-9.0.3.tgz#4bc6d2aea33191e4fed5ec71f039e2bbeb95e414" 516 | integrity sha512-SxIiD2yE/By79p3cNAAXyLQWTvEFNEzcAO7PH+DzRqKSFaplAPFjiQLmw8ofmpCsZf+Rhfn2/xCJagpdGmYdTw== 517 | dependencies: 518 | url-parse "^1.4.4" 519 | 520 | ms@2.0.0: 521 | version "2.0.0" 522 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 523 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 524 | 525 | nan@^2.14.0: 526 | version "2.14.1" 527 | resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" 528 | integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== 529 | 530 | next-tick@~1.0.0: 531 | version "1.0.0" 532 | resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" 533 | integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= 534 | 535 | node-fetch@2.1.2: 536 | version "2.1.2" 537 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" 538 | integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U= 539 | 540 | node-fetch@^2.6.1: 541 | version "2.6.1" 542 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" 543 | integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== 544 | 545 | node-gyp-build@^4.2.0: 546 | version "4.2.3" 547 | resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739" 548 | integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg== 549 | 550 | pbkdf2@^3.0.16, pbkdf2@^3.0.9: 551 | version "3.0.17" 552 | resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" 553 | integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== 554 | dependencies: 555 | create-hash "^1.1.2" 556 | create-hmac "^1.1.4" 557 | ripemd160 "^2.0.1" 558 | safe-buffer "^5.0.1" 559 | sha.js "^2.4.8" 560 | 561 | prettier@^2.0.5: 562 | version "2.0.5" 563 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" 564 | integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== 565 | 566 | protobufjs@^6.8.8: 567 | version "6.9.0" 568 | resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.9.0.tgz#c08b2bf636682598e6fabbf0edb0b1256ff090bd" 569 | integrity sha512-LlGVfEWDXoI/STstRDdZZKb/qusoAWUnmLg9R8OLSO473mBLWHowx8clbX5/+mKDEI+v7GzjoK9tRPZMMcoTrg== 570 | dependencies: 571 | "@protobufjs/aspromise" "^1.1.2" 572 | "@protobufjs/base64" "^1.1.2" 573 | "@protobufjs/codegen" "^2.0.4" 574 | "@protobufjs/eventemitter" "^1.1.0" 575 | "@protobufjs/fetch" "^1.1.0" 576 | "@protobufjs/float" "^1.0.2" 577 | "@protobufjs/inquire" "^1.1.0" 578 | "@protobufjs/path" "^1.1.2" 579 | "@protobufjs/pool" "^1.1.0" 580 | "@protobufjs/utf8" "^1.1.0" 581 | "@types/long" "^4.0.1" 582 | "@types/node" "^13.7.0" 583 | long "^4.0.0" 584 | 585 | querystringify@^2.1.1: 586 | version "2.2.0" 587 | resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" 588 | integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== 589 | 590 | randombytes@^2.0.1, randombytes@^2.0.6: 591 | version "2.1.0" 592 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 593 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 594 | dependencies: 595 | safe-buffer "^5.1.0" 596 | 597 | readable-stream@^3.6.0: 598 | version "3.6.0" 599 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" 600 | integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== 601 | dependencies: 602 | inherits "^2.0.3" 603 | string_decoder "^1.1.1" 604 | util-deprecate "^1.0.1" 605 | 606 | requires-port@^1.0.0: 607 | version "1.0.0" 608 | resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 609 | integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= 610 | 611 | ripemd160@^2.0.0, ripemd160@^2.0.1: 612 | version "2.0.2" 613 | resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" 614 | integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== 615 | dependencies: 616 | hash-base "^3.0.0" 617 | inherits "^2.0.1" 618 | 619 | safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: 620 | version "5.2.1" 621 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 622 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 623 | 624 | scrypt-js@^3.0.1: 625 | version "3.0.1" 626 | resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" 627 | integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== 628 | 629 | scryptsy@^2.1.0: 630 | version "2.1.0" 631 | resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790" 632 | integrity sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w== 633 | 634 | secp256k1@^3.0.1: 635 | version "3.8.0" 636 | resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.8.0.tgz#28f59f4b01dbee9575f56a47034b7d2e3b3b352d" 637 | integrity sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw== 638 | dependencies: 639 | bindings "^1.5.0" 640 | bip66 "^1.1.5" 641 | bn.js "^4.11.8" 642 | create-hash "^1.2.0" 643 | drbg.js "^1.0.1" 644 | elliptic "^6.5.2" 645 | nan "^2.14.0" 646 | safe-buffer "^5.1.2" 647 | 648 | sha.js@^2.4.0, sha.js@^2.4.8: 649 | version "2.4.11" 650 | resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" 651 | integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== 652 | dependencies: 653 | inherits "^2.0.1" 654 | safe-buffer "^5.0.1" 655 | 656 | sodium-native@^3.2.0: 657 | version "3.2.0" 658 | resolved "https://registry.yarnpkg.com/sodium-native/-/sodium-native-3.2.0.tgz#68a9469b96edadffef320cbce51294ad5f72a37f" 659 | integrity sha512-8aq/vQSegLwsRch8Sb/Bpf9aAqlNe5dp0+NVhb9UjHv42zDZ0D5zX3wBRUbXK9Ejum9uZE6DUgT4vVLlUFRBWg== 660 | dependencies: 661 | ini "^1.3.5" 662 | node-gyp-build "^4.2.0" 663 | 664 | string_decoder@^1.1.1: 665 | version "1.3.0" 666 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" 667 | integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== 668 | dependencies: 669 | safe-buffer "~5.2.0" 670 | 671 | tslib@^1.11.1: 672 | version "1.13.0" 673 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" 674 | integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== 675 | 676 | tslib@^1.11.2: 677 | version "1.11.2" 678 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.2.tgz#9c79d83272c9a7aaf166f73915c9667ecdde3cc9" 679 | integrity sha512-tTSkux6IGPnUGUd1XAZHcpu85MOkIl5zX49pO+jfsie3eP0B6pyhOlLXm3cAC6T7s+euSDDUUV+Acop5WmtkVg== 680 | 681 | tslint-config-prettier@^1.18.0: 682 | version "1.18.0" 683 | resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz#75f140bde947d35d8f0d238e0ebf809d64592c37" 684 | integrity sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg== 685 | 686 | type@^1.0.1: 687 | version "1.2.0" 688 | resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" 689 | integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== 690 | 691 | type@^2.0.0: 692 | version "2.0.0" 693 | resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" 694 | integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== 695 | 696 | typedarray-to-buffer@^3.1.5: 697 | version "3.1.5" 698 | resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" 699 | integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== 700 | dependencies: 701 | is-typedarray "^1.0.0" 702 | 703 | unorm@^1.3.3: 704 | version "1.6.0" 705 | resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" 706 | integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== 707 | 708 | url-parse@^1.4.4: 709 | version "1.5.1" 710 | resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.1.tgz#d5fa9890af8a5e1f274a2c98376510f6425f6e3b" 711 | integrity sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q== 712 | dependencies: 713 | querystringify "^2.1.1" 714 | requires-port "^1.0.0" 715 | 716 | util-deprecate@^1.0.1: 717 | version "1.0.2" 718 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 719 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 720 | 721 | utility-types@^2.1.0: 722 | version "2.1.0" 723 | resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-2.1.0.tgz#0c78fc9f7eb424d14302222b4ddd13fdb17f44ab" 724 | integrity sha512-/nP2gqavggo6l38rtQI/CdeV+2fmBGXVvHgj9kV2MAnms3TIi77Mz9BtapPFI0+GZQCqqom0vACQ+VlTTaCovw== 725 | 726 | utility-types@^3.4.1: 727 | version "3.10.0" 728 | resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" 729 | integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== 730 | 731 | uuid@^3.3.2: 732 | version "3.4.0" 733 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" 734 | integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== 735 | 736 | websocket@^1.0.28: 737 | version "1.0.31" 738 | resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.31.tgz#e5d0f16c3340ed87670e489ecae6144c79358730" 739 | integrity sha512-VAouplvGKPiKFDTeCCO65vYHsyay8DqoBSlzIO3fayrfOgU94lQN5a1uWVnFrMLceTJw/+fQXR5PGbUVRaHshQ== 740 | dependencies: 741 | debug "^2.2.0" 742 | es5-ext "^0.10.50" 743 | nan "^2.14.0" 744 | typedarray-to-buffer "^3.1.5" 745 | yaeti "^0.0.6" 746 | 747 | whatwg-fetch@2.0.4: 748 | version "2.0.4" 749 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" 750 | integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== 751 | 752 | whatwg-fetch@^3.4.1: 753 | version "3.4.1" 754 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.1.tgz#e5f871572d6879663fa5674c8f833f15a8425ab3" 755 | integrity sha512-sofZVzE1wKwO+EYPbWfiwzaKovWiZXf4coEzjGP9b2GBVgQRLQUZ2QcuPpQExGDAW5GItpEm6Tl4OU5mywnAoQ== 756 | 757 | yaeti@^0.0.6: 758 | version "0.0.6" 759 | resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" 760 | integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= 761 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import 'isomorphic-fetch' 2 | import { Zilliqa } from '@zilliqa-js/zilliqa' 3 | import { Wallet, Transaction, TxReceipt as _TxReceipt } from '@zilliqa-js/account' 4 | import { Contract, Value, CallParams } from '@zilliqa-js/contract' 5 | import { fromBech32Address, toBech32Address } from '@zilliqa-js/crypto' 6 | import { StatusType, MessageType, NewEventSubscription } from '@zilliqa-js/subscriptions' 7 | import { BN, Long, units } from '@zilliqa-js/util' 8 | import { BigNumber } from 'bignumber.js' 9 | import { Mutex } from 'async-mutex' 10 | 11 | import { APIS, WSS, CONTRACTS, CHAIN_VERSIONS, BASIS, Network, ZIL_HASH, WHITELISTED_TOKENS } from './constants' 12 | import { unitlessBigNumber, toPositiveQa, isLocalStorageAvailable } from './utils' 13 | import { sendBatchRequest, BatchRequest } from './batch' 14 | import { Zilo, OnStateUpdate } from './zilo' 15 | export * as Zilo from './zilo' 16 | 17 | BigNumber.config({ EXPONENTIAL_AT: 1e9 }) // never! 18 | 19 | export type Options = { 20 | deadlineBuffer?: number 21 | gasPrice?: number 22 | gasLimit?: number 23 | rpcEndpoint?: string 24 | } 25 | 26 | export type OnUpdate = (tx: ObservedTx, status: TxStatus, receipt?: TxReceipt) => void 27 | 28 | export type ObservedTx = { 29 | hash: string 30 | deadline: number 31 | } 32 | 33 | // The tx status of an observed tx. 34 | // Confirmed = txn was found, confirmed and processed without reverting 35 | // Rejected = txn was found, confirmed, but had an error and reverted during smart contract execution 36 | // Expired = current block height has exceeded the txn's deadline block 37 | export type TxStatus = 'confirmed' | 'rejected' | 'expired' 38 | 39 | export type TxReceipt = _TxReceipt 40 | 41 | export type TxParams = { 42 | version: number 43 | gasPrice: BN 44 | gasLimit: Long 45 | } 46 | 47 | export type TokenDetails = { 48 | contract: Contract // instance 49 | address: string 50 | hash: string 51 | name: string 52 | symbol: string 53 | decimals: number 54 | registered: boolean // is in default token list 55 | whitelisted: boolean // is a verified token 56 | } 57 | 58 | export type ContractState = { 59 | balances: { [key in string]?: { [key2 in string]?: string } } 60 | output_after_fee: string 61 | pools: { [key in string]?: { arguments: ReadonlyArray } } 62 | total_contributions: { [key in string]?: string } 63 | } 64 | 65 | export type AppState = { 66 | contractState: ContractState 67 | tokens: { [key in string]: TokenDetails } 68 | pools: { [key in string]?: Pool } 69 | currentUser: string | null 70 | currentNonce: number | null 71 | currentBalance: BigNumber | null 72 | } 73 | 74 | export type Pool = { 75 | zilReserve: BigNumber 76 | tokenReserve: BigNumber 77 | exchangeRate: BigNumber // the zero slippage exchange rate 78 | totalContribution: BigNumber 79 | userContribution: BigNumber 80 | contributionPercentage: BigNumber 81 | } 82 | 83 | export type Rates = { 84 | expectedAmount: BigNumber // in human amounts (with decimals) 85 | slippage: BigNumber // in percentage points 86 | } 87 | 88 | export type WalletProvider = Omit< 89 | Zilliqa & { wallet: Wallet & { net: string; defaultAccount: { base16: string; bech32: string } } }, // ugly hack for zilpay non-standard API 90 | 'subscriptionBuilder' 91 | > 92 | 93 | type RPCBalanceResponse = { balance: string; nonce: string } 94 | 95 | export class Zilswap { 96 | /* Zilliqa SDK */ 97 | readonly zilliqa: Zilliqa 98 | 99 | /* Internals */ 100 | private readonly rpcEndpoint: string 101 | private readonly walletProvider?: WalletProvider // zilpay 102 | private readonly tokens: { [key in string]: string } // symbol => hash mappings 103 | private appState?: AppState // cached blockchain state for dApp and user 104 | 105 | /* Txn observers */ 106 | private subscription: NewEventSubscription | null = null 107 | private observer: OnUpdate | null = null 108 | private observerMutex: Mutex 109 | private observedTxs: ObservedTx[] = [] 110 | 111 | /* Deadline tracking */ 112 | private deadlineBuffer: number = 3 113 | private currentBlock: number = -1 114 | 115 | /* Zilswap contract attributes */ 116 | readonly contract: Contract 117 | readonly contractAddress: string 118 | readonly contractHash: string 119 | 120 | /* Zilswap initial launch offerings */ 121 | readonly zilos: { [address: string]: Zilo } 122 | 123 | /* Transaction attributes */ 124 | readonly _txParams: TxParams = { 125 | version: -1, 126 | gasPrice: new BN(0), 127 | gasLimit: Long.fromNumber(5000), 128 | } 129 | 130 | /** 131 | * Creates the Zilswap SDK object. {@linkcode initalize} needs to be called after 132 | * the object is created to begin watching the blockchain's state. 133 | * 134 | * @param network the Network to use, either `TestNet` or `MainNet`. 135 | * @param walletProviderOrKey a Provider with Wallet or private key string to be used for signing txns. 136 | * @param options a set of Options that will be used for all txns. 137 | */ 138 | constructor(readonly network: Network, walletProviderOrKey?: WalletProvider | string, options?: Options) { 139 | this.rpcEndpoint = options?.rpcEndpoint || APIS[network] 140 | if (typeof walletProviderOrKey === 'string') { 141 | this.zilliqa = new Zilliqa(this.rpcEndpoint) 142 | this.zilliqa.wallet.addByPrivateKey(walletProviderOrKey) 143 | } else if (walletProviderOrKey) { 144 | this.zilliqa = new Zilliqa(this.rpcEndpoint, walletProviderOrKey.provider) 145 | this.walletProvider = walletProviderOrKey 146 | } else { 147 | this.zilliqa = new Zilliqa(this.rpcEndpoint) 148 | } 149 | 150 | this.contractAddress = CONTRACTS[network] 151 | this.contract = (this.walletProvider || this.zilliqa).contracts.at(this.contractAddress) 152 | this.contractHash = fromBech32Address(this.contractAddress).toLowerCase() 153 | this.tokens = {} 154 | this.zilos = {} 155 | this._txParams.version = CHAIN_VERSIONS[network] 156 | 157 | if (options) { 158 | if (options.deadlineBuffer && options.deadlineBuffer > 0) this.deadlineBuffer = options.deadlineBuffer 159 | if (options.gasPrice && options.gasPrice > 0) this._txParams.gasPrice = toPositiveQa(options.gasPrice, units.Units.Li) 160 | if (options.gasLimit && options.gasLimit > 0) this._txParams.gasLimit = Long.fromNumber(options.gasLimit) 161 | } 162 | 163 | this.observerMutex = new Mutex() 164 | } 165 | 166 | /** 167 | * Intializes the SDK, fetching a cache of the Zilswap contract state and 168 | * subscribing to subsequent state changes. You may optionally pass an array 169 | * of ObservedTx's to subscribe to status changes on any of those txs. 170 | * 171 | * @param subscription is the callback function to call when a tx state changes. 172 | * @param observedTx is the array of txs to observe. 173 | */ 174 | public async initialize(subscription?: OnUpdate, observeTxs: ObservedTx[] = []) { 175 | this.observedTxs = observeTxs 176 | if (subscription) this.observer = subscription 177 | if (this._txParams.gasPrice.isZero()) { 178 | const minGasPrice = await this.zilliqa.blockchain.getMinimumGasPrice() 179 | if (!minGasPrice.result) throw new Error('Failed to get min gas price.') 180 | this._txParams.gasPrice = new BN(minGasPrice.result) 181 | } 182 | await this.loadTokenList() 183 | await this.updateBlockHeight() 184 | await this.updateAppState() 185 | await this.updateBalanceAndNonce() 186 | } 187 | 188 | /** 189 | * Initializes a new Zilo instance and registers it to the ZilSwap SDK, 190 | * subscribing to subsequent state changes in the Zilo instance. You may 191 | * optionally pass a state observer to subscribe to state changes of this 192 | * particular Zilo instance. 193 | * 194 | * If the Zilo instance is already registered, no new instance will be 195 | * created. If a new state observer is provided, it will overwrite the 196 | * existing one. 197 | * 198 | * @param address is the Zilo contract address which can be given by 199 | * either hash (0x...) or bech32 address (zil...). 200 | * @param onStateUpdate is the state observer which triggers when state 201 | * updates 202 | */ 203 | public async registerZilo(address: string, onStateUpdate?: OnStateUpdate): Promise { 204 | const byStr20Address = this.parseRecipientAddress(address) 205 | 206 | if (this.zilos[byStr20Address]) { 207 | this.zilos[byStr20Address].updateObserver(onStateUpdate) 208 | return this.zilos[byStr20Address] 209 | } 210 | 211 | const zilo = new Zilo(this, byStr20Address) 212 | await zilo.initialize(onStateUpdate) 213 | this.zilos[byStr20Address] = zilo 214 | 215 | this.subscribeToAppChanges() 216 | 217 | return zilo 218 | } 219 | 220 | /** 221 | * Deregisters an existing Zilo instance. Does nothing if provided 222 | * address is not already registered. 223 | * 224 | * @param address is the Zilo contract address which can be given by 225 | * either hash (0x...) or bech32 address (zil...). 226 | */ 227 | public deregisterZilo(address: string) { 228 | const byStr20Address = this.parseRecipientAddress(address) 229 | 230 | if (!this.zilos[byStr20Address]) { 231 | return 232 | } 233 | 234 | delete this.zilos[address] 235 | 236 | this.subscribeToAppChanges() 237 | } 238 | 239 | /** 240 | * Stops watching the Zilswap contract state. 241 | */ 242 | public async teardown() { 243 | this.subscription?.stop() 244 | 245 | const stopped = new Promise(resolve => { 246 | const checkSubscription = () => { 247 | if (this.subscription) { 248 | setTimeout(checkSubscription, 100) 249 | } else { 250 | resolve() 251 | } 252 | } 253 | checkSubscription() 254 | }) 255 | await stopped 256 | } 257 | 258 | /** 259 | * Gets the latest Zilswap app state. 260 | */ 261 | public getAppState(): AppState { 262 | if (!this.appState) { 263 | throw new Error('App state not loaded, call #initialize first.') 264 | } 265 | return this.appState 266 | } 267 | 268 | /** 269 | * Gets the contract with the given address that can be called by the default account. 270 | */ 271 | public getContract(address: string): Contract { 272 | return (this.walletProvider || this.zilliqa).contracts.at(address) 273 | } 274 | 275 | /** 276 | * Gets the pool details for the given `tokenID`. 277 | * 278 | * @param tokenID is the token ID for the pool, which can be given by either it's symbol (defined in constants.ts), 279 | * hash (0x...) or bech32 address (zil...). 280 | * @returns {Pool} if pool exists, or `null` otherwise. 281 | */ 282 | public getPool(tokenID: string): Pool | null { 283 | if (!this.appState) { 284 | throw new Error('App state not loaded, call #initialize first.') 285 | } 286 | return this.appState.pools[this.getTokenAddresses(tokenID).hash] || null 287 | } 288 | 289 | /** 290 | * Gets the currently observed transactions. 291 | */ 292 | public async getObservedTxs(): Promise { 293 | const release = await this.observerMutex.acquire() 294 | try { 295 | return [...this.observedTxs] 296 | } finally { 297 | release() 298 | } 299 | } 300 | 301 | /** 302 | * Converts an amount to it's unitless representation (integer, no decimals) from it's 303 | * human representation (with decimals based on token contract, or 12 decimals for ZIL). 304 | * @param tokenID is the token ID related to the conversion amount, which can be given by either it's symbol (defined in constants.ts), 305 | * hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. 306 | * @param amountHuman is the amount as a human string (e.g. 4.2 for 4.2 ZILs) to be converted. 307 | */ 308 | public toUnitless(tokenID: string, amountHuman: string): string { 309 | const token = this.getTokenDetails(tokenID) 310 | const amountUnitless = new BigNumber(amountHuman).shiftedBy(token.decimals) 311 | if (!amountUnitless.integerValue().isEqualTo(amountUnitless)) { 312 | throw new Error(`Amount ${amountHuman} for ${token.symbol} has too many decimals, max is ${token.decimals}.`) 313 | } 314 | return amountUnitless.toString() 315 | } 316 | 317 | /** 318 | * Converts an amount to it's human representation (with decimals based on token contract, or 12 decimals for ZIL) 319 | * from it's unitless representation (integer, no decimals). 320 | * @param tokenID is the token ID related to the conversion amount, which can be given by either it's symbol (defined in constants.ts), 321 | * hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. 322 | * @param amountStr is the unitless amount as a string (e.g. 42000000000000 for 42 ZILs) to be converted. 323 | */ 324 | public toUnit(tokenID: string, amountStr: string): string { 325 | const token = this.getTokenDetails(tokenID) 326 | const amountBN = new BigNumber(amountStr) 327 | if (!amountBN.integerValue().isEqualTo(amountStr)) { 328 | throw new Error(`Amount ${amountStr} for ${token.symbol} cannot have decimals.`) 329 | } 330 | return amountBN.shiftedBy(-token.decimals).toString() 331 | } 332 | 333 | /** 334 | * Gets the expected output amount and slippage for a particular set of ZRC-2 or ZIL tokens at the given input amount. 335 | * 336 | * @param tokenInID is the token ID to be sent to Zilswap (sold), which can be given by either it's symbol (defined in constants.ts), 337 | * hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. 338 | * @param tokenOutID is the token ID to be taken from Zilswap (bought), which can be given by either it's symbol (defined in constants.ts), 339 | * hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. 340 | * @param tokenInAmountStr is the exact amount of tokens to be sent to Zilswap as a unitless representable string (without decimals). 341 | */ 342 | public getRatesForInput(tokenInID: string, tokenOutID: string, tokenInAmountStr: string): Rates { 343 | const tokenIn = this.getTokenDetails(tokenInID) 344 | const tokenOut = this.getTokenDetails(tokenOutID) 345 | const tokenInAmount = unitlessBigNumber(tokenInAmountStr) 346 | const { epsilonOutput, expectedOutput } = this.getOutputs(tokenIn, tokenOut, tokenInAmount) 347 | 348 | return { 349 | expectedAmount: expectedOutput, 350 | slippage: epsilonOutput.minus(expectedOutput).times(100).dividedBy(epsilonOutput).minus(0.3), 351 | } 352 | } 353 | 354 | /** 355 | * Gets the expected input amount and slippage for a particular set of ZRC-2 or ZIL tokens at the given output amount. 356 | * Returns NaN values if the given output amount is larger than the pool reserve. 357 | * 358 | * @param tokenInID is the token ID to be sent to Zilswap (sold), which can be given by either it's symbol (defined in constants.ts), 359 | * hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. 360 | * @param tokenOutID is the token ID to be taken from Zilswap (bought), which can be given by either it's symbol (defined in constants.ts), 361 | * hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. 362 | * @param tokenOutAmountStr is the exact amount of tokens to be received from Zilswap as a unitless representable string (without decimals). 363 | */ 364 | public getRatesForOutput(tokenInID: string, tokenOutID: string, tokenOutAmountStr: string): Rates { 365 | const tokenIn = this.getTokenDetails(tokenInID) 366 | const tokenOut = this.getTokenDetails(tokenOutID) 367 | const tokenOutAmount = unitlessBigNumber(tokenOutAmountStr) 368 | const { epsilonInput, expectedInput } = this.getInputs(tokenIn, tokenOut, tokenOutAmount) 369 | 370 | return { 371 | expectedAmount: expectedInput, 372 | slippage: expectedInput.minus(epsilonInput).times(100).dividedBy(expectedInput).minus(0.3), 373 | } 374 | } 375 | 376 | /** 377 | * Sets the number of blocks to use as the allowable buffer duration before transactions 378 | * are considered invalid. 379 | * 380 | * When a transaction is signed, the deadline block by adding the buffer blocks to 381 | * the latest confirmed block height. 382 | * 383 | * @param bufferBlocks is the number of blocks to use as buffer for the deadline block. 384 | */ 385 | public setDeadlineBlocks(bufferBlocks: number) { 386 | if (bufferBlocks <= 0) { 387 | throw new Error('Buffer blocks must be greater than 0.') 388 | } 389 | this.deadlineBuffer = bufferBlocks 390 | } 391 | 392 | /** 393 | * Observes the given transaction until the deadline block. 394 | * 395 | * Calls the `OnUpdate` callback given during `initialize` with the updated ObservedTx 396 | * when a change has been observed. 397 | * 398 | * @param observedTx is the txn hash of the txn to observe with the deadline block number. 399 | */ 400 | public async observeTx(observedTx: ObservedTx) { 401 | const release = await this.observerMutex.acquire() 402 | try { 403 | this.observedTxs.push(observedTx) 404 | } finally { 405 | release() 406 | } 407 | } 408 | 409 | /** 410 | * Adds a token which is not already loaded by the default tokens file to the SDK. 411 | * @param tokenAddress is the token address in base16 (0x...) or bech32 (zil...) form. 412 | * 413 | * @returns true if the token could be found, or false otherwise. 414 | */ 415 | public async addToken(tokenAddress: string): Promise { 416 | if (!this.appState) { 417 | throw new Error('App state not loaded, call #initialize first.') 418 | } 419 | try { 420 | const details = await this.fetchTokenDetails(tokenAddress) 421 | if (details === null) return false 422 | this.appState!.tokens[details.hash] = details 423 | return true 424 | } catch { 425 | return false 426 | } 427 | } 428 | 429 | /** 430 | * Approves allowing the Zilswap contract to transfer ZRC-2 token with `tokenID`, if the current 431 | * approved allowance is less than `amount`. If the allowance is sufficient, this method is a no-op. 432 | * 433 | * The approval is done by calling `IncreaseAllowance` with the allowance amount as the entire 434 | * token supply. This is done so that the approval needs to only be done once per token contract, 435 | * reducing the number of approval transactions required for users conducting multiple swaps. 436 | * 437 | * Non-custodial control of the token is ensured by the Zilswap contract itself, which does not 438 | * allow for the transfer of tokens unless explicitly invoked by the sender. 439 | * 440 | * The transaction is added to the list of observedTxs, and the observer will be notified on 441 | * a confirmation or rejection event. The transation will be assumed to be expired after the default 442 | * deadline buffer, even though there is no deadline block for this transaction. 443 | * 444 | * @param tokenID is the token ID for the pool, which can be given by either it's symbol (defined in constants.ts), 445 | * hash (0x...) or bech32 address (zil...). 446 | * @param amountStrOrBN is the required allowance amount the Zilswap contract requires, below which the 447 | * `IncreaseAllowance` transition is invoked, as a unitless string or BigNumber. 448 | * @param spenderHash (optional) is the spender contract address, defaults to the ZilSwap contract address. 449 | * 450 | * @returns an ObservedTx if IncreaseAllowance was called, null if not. 451 | */ 452 | public async approveTokenTransferIfRequired( 453 | tokenID: string, 454 | amountStrOrBN: BigNumber | string, 455 | spenderHash: string = this.contractHash 456 | ): Promise { 457 | // Check logged in 458 | this.checkAppLoadedWithUser() 459 | 460 | const _spenderHash = this.parseRecipientAddress(spenderHash) 461 | const token = this.getTokenDetails(tokenID) 462 | const tokenState = await token.contract.getSubState('allowances', [this.appState!.currentUser!, _spenderHash]) 463 | const allowance = new BigNumber(tokenState?.allowances[this.appState!.currentUser!]?.[_spenderHash] || 0) 464 | const amount: BigNumber = typeof amountStrOrBN === 'string' ? unitlessBigNumber(amountStrOrBN) : amountStrOrBN 465 | 466 | if (allowance.lt(amount)) { 467 | try { 468 | console.log('sending increase allowance txn..') 469 | const approveTxn = await this.callContract( 470 | token.contract, 471 | 'IncreaseAllowance', 472 | [ 473 | { 474 | vname: 'spender', 475 | type: 'ByStr20', 476 | value: _spenderHash, 477 | }, 478 | { 479 | vname: 'amount', 480 | type: 'Uint128', 481 | value: new BigNumber(2).pow(128).minus(1).minus(allowance).toString(), 482 | }, 483 | ], 484 | { 485 | amount: new BN(0), 486 | ...this.txParams(), 487 | }, 488 | true 489 | ) 490 | 491 | const observeTxn = { 492 | hash: approveTxn.id!, 493 | deadline: this.deadlineBlock(), 494 | } 495 | await this.observeTx(observeTxn) 496 | 497 | return observeTxn 498 | } catch (err) { 499 | if ((err as any).message === 'Could not get balance') { 500 | throw new Error('No ZIL to pay for transaction.') 501 | } else { 502 | throw err 503 | } 504 | } 505 | } 506 | 507 | return null 508 | } 509 | 510 | /** 511 | * Adds liquidity to the pool with the given `tokenID`. The given `zilsToAddHuman` represents the exact quantity of ZIL 512 | * that will be contributed, while the given `tokensToAddHuman` represents the target quantity of ZRC-2 tokens to be 513 | * contributed. 514 | * 515 | * To ensure the liquidity contributor does not lose value to arbitrage, the target token amount should be strictly 516 | * derived from the current exchange rate that can be found using {@linkcode getPool}. 517 | * 518 | * The maximum fluctuation in exchange rate from the given parameters can be controlled through `maxExchangeRateChange`, 519 | * to protect against changes in pool reserves between the txn submission and txn confirmation on the Zilliqa blockchain. 520 | * 521 | * If the pool has no liquidity yet, the token amount given will be the exact quantity of tokens that will be contributed, 522 | * and the `maxExchangeRateChange` is ignored. 523 | * 524 | * The transaction is added to the list of observedTxs, and the observer will be notified on change in tx status. 525 | * 526 | * Note that all amounts should be given with decimals in it's human represented form, rather than as a unitless integer. 527 | * 528 | * @param tokenID is the token ID for the pool, which can be given by either it's symbol (defined in constants.ts), 529 | * hash (0x...) or bech32 address (zil...). 530 | * @param zilsToAddStr is the exact amount of zilliqas to contribute to the pool in ZILs as a unitless string. 531 | * @param tokensToAddStr is the target amount of tokens to contribute to the pool as a unitless string. 532 | * @param maxExchangeRateChange is the maximum allowed exchange rate flucuation 533 | * given in {@link https://www.investopedia.com/terms/b/basispoint.asp basis points}. Defaults to 200 = 2.00% if not provided. 534 | */ 535 | public async addLiquidity( 536 | tokenID: string, 537 | zilsToAddStr: string, 538 | tokensToAddStr: string, 539 | maxExchangeRateChange: number = 200 540 | ): Promise { 541 | // Check logged in 542 | this.checkAppLoadedWithUser() 543 | 544 | // Format token amounts 545 | const token = this.getTokenDetails(tokenID) 546 | const zil = this.getTokenDetails(ZIL_HASH) 547 | const tokensToAdd = new BigNumber(tokensToAddStr) 548 | const zilsToAdd = new BigNumber(zilsToAddStr) 549 | 550 | // Calculate allowances 551 | const pool = this.getPool(token.hash) 552 | const maxTokens = pool ? tokensToAdd.times(BASIS + maxExchangeRateChange).dividedToIntegerBy(BASIS) : tokensToAdd 553 | let minContribution = new BN(0) 554 | if (pool) { 555 | // sqrt(delta) * x = max allowed change in zil reserve 556 | // min contribution = zil added / max zil reserve * current total contributions 557 | const { zilReserve } = pool 558 | this.validateMaxExchangeRateChange(maxExchangeRateChange) 559 | const totalContribution = pool.totalContribution 560 | const numerator = totalContribution.times(zilsToAdd.toString()) 561 | const denominator = new BigNumber(BASIS).plus(maxExchangeRateChange).sqrt().times(zilReserve.toString()) 562 | minContribution = new BN(numerator.dividedToIntegerBy(denominator).toString()) 563 | } 564 | 565 | // Check balances 566 | await this.checkAllowedBalance(token, tokensToAdd) 567 | await this.checkAllowedBalance(zil, zilsToAdd) 568 | 569 | const deadline = this.deadlineBlock() 570 | 571 | console.log('sending add liquidity txn..') 572 | const addLiquidityTxn = await this.callContract( 573 | this.contract, 574 | 'AddLiquidity', 575 | [ 576 | { 577 | vname: 'token_address', 578 | type: 'ByStr20', 579 | value: token.hash, 580 | }, 581 | { 582 | vname: 'min_contribution_amount', 583 | type: 'Uint128', 584 | value: minContribution.toString(), 585 | }, 586 | { 587 | vname: 'max_token_amount', 588 | type: 'Uint128', 589 | value: maxTokens.toString(), 590 | }, 591 | { 592 | vname: 'deadline_block', 593 | type: 'BNum', 594 | value: deadline.toString(), 595 | }, 596 | ], 597 | { 598 | amount: new BN(zilsToAdd.toString()), // _amount 599 | ...this.txParams(), 600 | }, 601 | true 602 | ) 603 | 604 | if (addLiquidityTxn.isRejected()) { 605 | throw new Error('Submitted transaction was rejected.') 606 | } 607 | 608 | const observeTxn = { 609 | hash: addLiquidityTxn.id!, 610 | deadline, 611 | } 612 | await this.observeTx(observeTxn) 613 | 614 | return observeTxn 615 | } 616 | 617 | /** 618 | * Removes `contributionAmount` worth of liquidity from the pool with the given `tokenID`. 619 | * 620 | * The current user's contribution can be fetched in {@linkcode getPool}, and the expected returned amounts at the 621 | * current prevailing exchange rates can be calculated by prorating the liquidity pool reserves by the fraction of 622 | * the user's current contribution against the pool's total contribution. 623 | * 624 | * The maximum fluctuation in exchange rate from the given parameters can be controlled through `maxExchangeRateChange`, 625 | * to protect against changes in pool reserves between the txn submission and txn confirmation on the Zilliqa blockchain. 626 | * 627 | * The transaction is added to the list of observedTxs, and the observer will be notified on change in tx status. 628 | * 629 | * @param tokenID is the token ID for the pool, which can be given by either it's symbol (defined in constants.ts), 630 | * hash (0x...) or bech32 address (zil...). 631 | * @param contributionAmount is the exact amount of zilliqas to contribute to the pool in ZILs as a string. 632 | * @param maxExchangeRateChange is the maximum allowed exchange rate flucuation 633 | * given in {@link https://www.investopedia.com/terms/b/basispoint.asp basis points}. Defaults to 200 = 2.00% if not provided. 634 | */ 635 | public async removeLiquidity(tokenID: string, contributionAmount: string, maxExchangeRateChange: number = 200): Promise { 636 | // Check logged in 637 | this.checkAppLoadedWithUser() 638 | 639 | // Check parameters 640 | this.validateMaxExchangeRateChange(maxExchangeRateChange) 641 | 642 | // Calculate contribution 643 | const token = this.getTokenDetails(tokenID) 644 | const pool = this.getPool(token.hash) 645 | if (!pool) { 646 | throw new Error('Pool not found.') 647 | } 648 | 649 | const { zilReserve, tokenReserve, userContribution, contributionPercentage } = pool 650 | // expected = reserve * (contributionPercentage / 100) * (contributionAmount / userContribution) 651 | const expectedZilAmount = zilReserve.times(contributionPercentage).times(contributionAmount).dividedBy(userContribution.times(100)) 652 | const expectedTokenAmount = tokenReserve.times(contributionPercentage).times(contributionAmount).dividedBy(userContribution.times(100)) 653 | const minZilAmount = expectedZilAmount.times(BASIS).dividedToIntegerBy(BASIS + maxExchangeRateChange) 654 | const minTokenAmount = expectedTokenAmount.times(BASIS).dividedToIntegerBy(BASIS + maxExchangeRateChange) 655 | 656 | // Check contribution 657 | if (userContribution.lt(contributionAmount)) { 658 | throw new Error('Trying to remove more contribution than available.') 659 | } 660 | 661 | const deadline = this.deadlineBlock() 662 | 663 | console.log('sending remove liquidity txn..') 664 | const removeLiquidityTxn = await this.callContract( 665 | this.contract, 666 | 'RemoveLiquidity', 667 | [ 668 | { 669 | vname: 'token_address', 670 | type: 'ByStr20', 671 | value: token.hash, 672 | }, 673 | { 674 | vname: 'contribution_amount', 675 | type: 'Uint128', 676 | value: contributionAmount, 677 | }, 678 | { 679 | vname: 'min_zil_amount', 680 | type: 'Uint128', 681 | value: minZilAmount.toString(), 682 | }, 683 | { 684 | vname: 'min_token_amount', 685 | type: 'Uint128', 686 | value: minTokenAmount.toString(), 687 | }, 688 | { 689 | vname: 'deadline_block', 690 | type: 'BNum', 691 | value: deadline.toString(), 692 | }, 693 | ], 694 | { 695 | amount: new BN(0), 696 | ...this.txParams(), 697 | }, 698 | true 699 | ) 700 | 701 | if (removeLiquidityTxn.isRejected()) { 702 | throw new Error('Submitted transaction was rejected.') 703 | } 704 | 705 | const observeTxn = { 706 | hash: removeLiquidityTxn.id!, 707 | deadline, 708 | } 709 | await this.observeTx(observeTxn) 710 | 711 | return observeTxn 712 | } 713 | 714 | /** 715 | * Swaps ZIL or a ZRC-2 token with `tokenInID` for a corresponding ZIL or ZRC-2 token with `tokenOutID`. 716 | * 717 | * The exact amount of ZIL or ZRC-2 to be sent in (sold) is `tokenInAmountHuman`. The amount received is determined by the prevailing 718 | * exchange rate at the current AppState. The expected amount to be received can be given fetched by getExpectedOutput (NYI). 719 | * 720 | * The maximum additional slippage incurred due to fluctuations in exchange rate from when the 721 | * transaction is signed and when it is processed by the Zilliqa blockchain can be bounded by the 722 | * `maxAdditionalSlippage` variable. 723 | * 724 | * The transaction is added to the list of observedTxs, and the observer will be notified on change in tx status. 725 | * 726 | * @param tokenInID is the token ID to be sent to Zilswap (sold), which can be given by either it's symbol (defined in constants.ts), 727 | * hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. 728 | * @param tokenOutID is the token ID to be taken from Zilswap (bought), which can be given by either it's symbol (defined in constants.ts), 729 | * hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. 730 | * @param tokenInAmountStr is the exact amount of tokens to be sent to Zilswap as a unitless string (without decimals). 731 | * @param maxAdditionalSlippage is the maximum additional slippage (on top of slippage due to constant product formula) that the 732 | * transition will allow before reverting. 733 | * @param recipientAddress is an optional recipient address for receiving the output of the swap in base16 (0x...) or bech32 (zil...). 734 | * Defaults to the sender address if `null` or undefined. 735 | */ 736 | public async swapWithExactInput( 737 | tokenInID: string, 738 | tokenOutID: string, 739 | tokenInAmountStr: string, 740 | maxAdditionalSlippage: number = 200, 741 | recipientAddress: string | null = null 742 | ): Promise { 743 | this.checkAppLoadedWithUser() 744 | 745 | const tokenIn = this.getTokenDetails(tokenInID) 746 | const tokenOut = this.getTokenDetails(tokenOutID) 747 | const tokenInAmount = unitlessBigNumber(tokenInAmountStr) 748 | const { expectedOutput } = this.getOutputs(tokenIn, tokenOut, tokenInAmount) 749 | const minimumOutput = expectedOutput.times(BASIS).dividedToIntegerBy(BASIS + maxAdditionalSlippage) 750 | const parsedRecipientAddress = this.parseRecipientAddress(recipientAddress) 751 | 752 | await this.checkAllowedBalance(tokenIn, tokenInAmount) 753 | 754 | const deadline = this.deadlineBlock() 755 | 756 | let txn: { transition: string; args: Value[]; params: CallParams } 757 | 758 | if (tokenIn.hash === ZIL_HASH) { 759 | // zil to zrc2 760 | txn = { 761 | transition: 'SwapExactZILForTokens', 762 | args: [ 763 | { 764 | vname: 'token_address', 765 | type: 'ByStr20', 766 | value: tokenOut.hash, 767 | }, 768 | { 769 | vname: 'min_token_amount', 770 | type: 'Uint128', 771 | value: minimumOutput.toString(), 772 | }, 773 | { 774 | vname: 'deadline_block', 775 | type: 'BNum', 776 | value: deadline.toString(), 777 | }, 778 | { 779 | vname: 'recipient_address', 780 | type: 'ByStr20', 781 | value: parsedRecipientAddress, 782 | }, 783 | ], 784 | params: { 785 | amount: new BN(tokenInAmount.toString()), 786 | ...this.txParams(), 787 | }, 788 | } 789 | } else if (tokenOut.hash === ZIL_HASH) { 790 | // zrc2 to zil 791 | txn = { 792 | transition: 'SwapExactTokensForZIL', 793 | args: [ 794 | { 795 | vname: 'token_address', 796 | type: 'ByStr20', 797 | value: tokenIn.hash, 798 | }, 799 | { 800 | vname: 'token_amount', 801 | type: 'Uint128', 802 | value: tokenInAmount.toString(), 803 | }, 804 | { 805 | vname: 'min_zil_amount', 806 | type: 'Uint128', 807 | value: minimumOutput.toString(), 808 | }, 809 | { 810 | vname: 'deadline_block', 811 | type: 'BNum', 812 | value: deadline.toString(), 813 | }, 814 | { 815 | vname: 'recipient_address', 816 | type: 'ByStr20', 817 | value: parsedRecipientAddress, 818 | }, 819 | ], 820 | params: { 821 | amount: new BN(0), 822 | ...this.txParams(), 823 | }, 824 | } 825 | } else { 826 | // zrc2 to zrc2 827 | txn = { 828 | transition: 'SwapExactTokensForTokens', 829 | args: [ 830 | { 831 | vname: 'token0_address', 832 | type: 'ByStr20', 833 | value: tokenIn.hash, 834 | }, 835 | { 836 | vname: 'token1_address', 837 | type: 'ByStr20', 838 | value: tokenOut.hash, 839 | }, 840 | { 841 | vname: 'token0_amount', 842 | type: 'Uint128', 843 | value: tokenInAmount.toString(), 844 | }, 845 | { 846 | vname: 'min_token1_amount', 847 | type: 'Uint128', 848 | value: minimumOutput.toString(), 849 | }, 850 | { 851 | vname: 'deadline_block', 852 | type: 'BNum', 853 | value: deadline.toString(), 854 | }, 855 | { 856 | vname: 'recipient_address', 857 | type: 'ByStr20', 858 | value: parsedRecipientAddress, 859 | }, 860 | ], 861 | params: { 862 | amount: new BN(0), 863 | ...this.txParams(), 864 | }, 865 | } 866 | } 867 | 868 | console.log('sending swap txn..') 869 | const swapTxn = await this.callContract(this.contract, txn.transition, txn.args, txn.params, true) 870 | 871 | if (swapTxn.isRejected()) { 872 | throw new Error('Submitted transaction was rejected.') 873 | } 874 | 875 | const observeTxn = { 876 | hash: swapTxn.id!, 877 | deadline, 878 | } 879 | await this.observeTx(observeTxn) 880 | 881 | return observeTxn 882 | } 883 | 884 | /** 885 | * Swaps ZIL or a ZRC-2 token with `tokenInID` for a corresponding ZIL or ZRC-2 token with `tokenOutID`. 886 | * 887 | * The exact amount of ZIL or ZRC-2 to be received (bought) is `tokenOutAmountHuman`. The amount sent is determined by the prevailing 888 | * exchange rate at the current AppState. The expected amount to be sent can be given fetched by getExpectedInput (NYI). 889 | * 890 | * The maximum additional slippage incurred due to fluctuations in exchange rate from when the 891 | * transaction is signed and when it is processed by the Zilliqa blockchain can be bounded by the 892 | * `maxAdditionalSlippage` variable. 893 | * 894 | * The transaction is added to the list of observedTxs, and the observer will be notified on change in tx status. 895 | * 896 | * @param tokenInID is the token ID to be sent to Zilswap (sold), which can be given by either it's symbol (defined in constants.ts), 897 | * hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. 898 | * @param tokenOutID is the token ID to be taken from Zilswap (bought), which can be given by either it's symbol (defined in constants.ts), 899 | * hash (0x...) or bech32 address (zil...). The hash for ZIL is represented by the ZIL_HASH constant. 900 | * @param tokenOutAmountStr is the exact amount of tokens to be received from Zilswap as a unitless string (withoout decimals). 901 | * @param maxAdditionalSlippage is the maximum additional slippage (on top of slippage due to constant product formula) that the 902 | * transition will allow before reverting. 903 | * @param recipientAddress is an optional recipient address for receiving the output of the swap in base16 (0x...) or bech32 (zil...). 904 | * Defaults to the sender address if `null` or undefined. 905 | */ 906 | public async swapWithExactOutput( 907 | tokenInID: string, 908 | tokenOutID: string, 909 | tokenOutAmountStr: string, 910 | maxAdditionalSlippage: number = 200, 911 | recipientAddress: string | null = null 912 | ): Promise { 913 | this.checkAppLoadedWithUser() 914 | 915 | const tokenIn = this.getTokenDetails(tokenInID) 916 | const tokenOut = this.getTokenDetails(tokenOutID) 917 | const tokenOutAmount = unitlessBigNumber(tokenOutAmountStr) 918 | const { expectedInput } = this.getInputs(tokenIn, tokenOut, tokenOutAmount) 919 | const maximumInput = expectedInput.times(BASIS + maxAdditionalSlippage).dividedToIntegerBy(BASIS) 920 | const parsedRecipientAddress = this.parseRecipientAddress(recipientAddress) 921 | 922 | await this.checkAllowedBalance(tokenIn, maximumInput) 923 | 924 | const deadline = this.deadlineBlock() 925 | 926 | let txn: { transition: string; args: Value[]; params: CallParams } 927 | 928 | if (tokenIn.hash === ZIL_HASH) { 929 | // zil to zrc2 930 | txn = { 931 | transition: 'SwapZILForExactTokens', 932 | args: [ 933 | { 934 | vname: 'token_address', 935 | type: 'ByStr20', 936 | value: tokenOut.hash, 937 | }, 938 | { 939 | vname: 'token_amount', 940 | type: 'Uint128', 941 | value: tokenOutAmount.toString(), 942 | }, 943 | { 944 | vname: 'deadline_block', 945 | type: 'BNum', 946 | value: deadline.toString(), 947 | }, 948 | { 949 | vname: 'recipient_address', 950 | type: 'ByStr20', 951 | value: parsedRecipientAddress, 952 | }, 953 | ], 954 | params: { 955 | amount: new BN(maximumInput.toString()), 956 | ...this.txParams(), 957 | }, 958 | } 959 | } else if (tokenOut.hash === ZIL_HASH) { 960 | // zrc2 to zil 961 | txn = { 962 | transition: 'SwapTokensForExactZIL', 963 | args: [ 964 | { 965 | vname: 'token_address', 966 | type: 'ByStr20', 967 | value: tokenIn.hash, 968 | }, 969 | { 970 | vname: 'max_token_amount', 971 | type: 'Uint128', 972 | value: maximumInput.toString(), 973 | }, 974 | { 975 | vname: 'zil_amount', 976 | type: 'Uint128', 977 | value: tokenOutAmount.toString(), 978 | }, 979 | { 980 | vname: 'deadline_block', 981 | type: 'BNum', 982 | value: deadline.toString(), 983 | }, 984 | { 985 | vname: 'recipient_address', 986 | type: 'ByStr20', 987 | value: parsedRecipientAddress, 988 | }, 989 | ], 990 | params: { 991 | amount: new BN(0), 992 | ...this.txParams(), 993 | }, 994 | } 995 | } else { 996 | // zrc2 to zrc2 997 | txn = { 998 | transition: 'SwapTokensForExactTokens', 999 | args: [ 1000 | { 1001 | vname: 'token0_address', 1002 | type: 'ByStr20', 1003 | value: tokenIn.hash, 1004 | }, 1005 | { 1006 | vname: 'token1_address', 1007 | type: 'ByStr20', 1008 | value: tokenOut.hash, 1009 | }, 1010 | { 1011 | vname: 'max_token0_amount', 1012 | type: 'Uint128', 1013 | value: maximumInput.toString(), 1014 | }, 1015 | { 1016 | vname: 'token1_amount', 1017 | type: 'Uint128', 1018 | value: tokenOutAmount.toString(), 1019 | }, 1020 | { 1021 | vname: 'deadline_block', 1022 | type: 'BNum', 1023 | value: deadline.toString(), 1024 | }, 1025 | { 1026 | vname: 'recipient_address', 1027 | type: 'ByStr20', 1028 | value: parsedRecipientAddress, 1029 | }, 1030 | ], 1031 | params: { 1032 | amount: new BN(0), 1033 | ...this.txParams(), 1034 | }, 1035 | } 1036 | } 1037 | 1038 | console.log('sending swap txn..') 1039 | const swapTxn = await this.callContract(this.contract, txn.transition, txn.args, txn.params, true) 1040 | 1041 | if (swapTxn.isRejected()) { 1042 | throw new Error('Submitted transaction was rejected.') 1043 | } 1044 | 1045 | const observeTxn = { 1046 | hash: swapTxn.id!, 1047 | deadline, 1048 | } 1049 | await this.observeTx(observeTxn) 1050 | 1051 | return observeTxn 1052 | } 1053 | 1054 | private getInputs( 1055 | tokenIn: TokenDetails, 1056 | tokenOut: TokenDetails, 1057 | tokenOutAmount: BigNumber 1058 | ): { epsilonInput: BigNumber; expectedInput: BigNumber } { 1059 | let expectedInput: BigNumber // the expected amount after slippage and fees 1060 | let epsilonInput: BigNumber // the zero slippage input 1061 | 1062 | if (tokenIn.hash === ZIL_HASH) { 1063 | // zil to zrc2 1064 | const { zilReserve, tokenReserve } = this.getReserves(tokenOut) 1065 | epsilonInput = tokenOutAmount.times(zilReserve).dividedToIntegerBy(tokenReserve) 1066 | expectedInput = this.getInputFor(tokenOutAmount, zilReserve, tokenReserve) 1067 | } else if (tokenOut.hash === ZIL_HASH) { 1068 | // zrc2 to zil 1069 | const { zilReserve, tokenReserve } = this.getReserves(tokenIn) 1070 | epsilonInput = tokenOutAmount.times(tokenReserve).dividedToIntegerBy(zilReserve) 1071 | expectedInput = this.getInputFor(tokenOutAmount, tokenReserve, zilReserve) 1072 | } else { 1073 | // zrc2 to zrc2 1074 | const { zilReserve: zr1, tokenReserve: tr1 } = this.getReserves(tokenOut) 1075 | const intermediateEpsilonInput = tokenOutAmount.times(zr1).dividedToIntegerBy(tr1) 1076 | const intermediateInput = this.getInputFor(tokenOutAmount, zr1, tr1) 1077 | 1078 | const { zilReserve: zr2, tokenReserve: tr2 } = this.getReserves(tokenIn) 1079 | epsilonInput = intermediateEpsilonInput.times(tr2).dividedToIntegerBy(zr2) 1080 | expectedInput = this.getInputFor(intermediateInput, tr2, zr2) 1081 | } 1082 | 1083 | return { epsilonInput, expectedInput } 1084 | } 1085 | 1086 | private getOutputs( 1087 | tokenIn: TokenDetails, 1088 | tokenOut: TokenDetails, 1089 | tokenInAmount: BigNumber 1090 | ): { epsilonOutput: BigNumber; expectedOutput: BigNumber } { 1091 | let epsilonOutput: BigNumber // the zero slippage output 1092 | let expectedOutput: BigNumber // the expected amount after slippage and fees 1093 | 1094 | if (tokenIn.hash === ZIL_HASH) { 1095 | // zil to zrc2 1096 | const { zilReserve, tokenReserve } = this.getReserves(tokenOut) 1097 | epsilonOutput = tokenInAmount.times(tokenReserve).dividedToIntegerBy(zilReserve) 1098 | expectedOutput = this.getOutputFor(tokenInAmount, zilReserve, tokenReserve) 1099 | } else if (tokenOut.hash === ZIL_HASH) { 1100 | // zrc2 to zil 1101 | const { zilReserve, tokenReserve } = this.getReserves(tokenIn) 1102 | epsilonOutput = tokenInAmount.times(zilReserve).dividedToIntegerBy(tokenReserve) 1103 | expectedOutput = this.getOutputFor(tokenInAmount, tokenReserve, zilReserve) 1104 | } else { 1105 | // zrc2 to zrc2 1106 | const { zilReserve: zr1, tokenReserve: tr1 } = this.getReserves(tokenIn) 1107 | const intermediateEpsilonOutput = tokenInAmount.times(zr1).dividedToIntegerBy(tr1) 1108 | const intermediateOutput = this.getOutputFor(tokenInAmount, tr1, zr1) 1109 | 1110 | const { zilReserve: zr2, tokenReserve: tr2 } = this.getReserves(tokenOut) 1111 | epsilonOutput = intermediateEpsilonOutput.times(tr2).dividedToIntegerBy(zr2) 1112 | expectedOutput = this.getOutputFor(intermediateOutput, zr2, tr2) 1113 | } 1114 | 1115 | return { epsilonOutput, expectedOutput } 1116 | } 1117 | 1118 | private getInputFor(outputAmount: BigNumber, inputReserve: BigNumber, outputReserve: BigNumber): BigNumber { 1119 | if (inputReserve.isZero() || outputReserve.isZero()) { 1120 | throw new Error('Reserve has 0 tokens.') 1121 | } 1122 | if (outputReserve.lte(outputAmount)) { 1123 | return new BigNumber('NaN') 1124 | } 1125 | const numerator = inputReserve.times(outputAmount).times(10000) 1126 | const denominator = outputReserve.minus(outputAmount).times(this.getAfterFeeBps()) 1127 | return numerator.dividedToIntegerBy(denominator).plus(1) 1128 | } 1129 | 1130 | private getOutputFor(inputAmount: BigNumber, inputReserve: BigNumber, outputReserve: BigNumber): BigNumber { 1131 | if (inputReserve.isZero() || outputReserve.isZero()) { 1132 | throw new Error('Reserve has 0 tokens.') 1133 | } 1134 | const inputAfterFee = inputAmount.times(this.getAfterFeeBps()) 1135 | const numerator = inputAfterFee.times(outputReserve) 1136 | const denominator = inputReserve.times(10000).plus(inputAfterFee) 1137 | return numerator.dividedToIntegerBy(denominator) 1138 | } 1139 | 1140 | private getAfterFeeBps(): string { 1141 | return this.getAppState().contractState.output_after_fee 1142 | } 1143 | 1144 | private getReserves(token: TokenDetails) { 1145 | const pool = this.getPool(token.hash) 1146 | 1147 | if (!pool) { 1148 | return { 1149 | zilReserve: new BigNumber(0), 1150 | tokenReserve: new BigNumber(0), 1151 | } 1152 | } 1153 | 1154 | const { zilReserve, tokenReserve } = pool 1155 | return { zilReserve, tokenReserve } 1156 | } 1157 | 1158 | public async callContract( 1159 | contract: Contract, 1160 | transition: string, 1161 | args: Value[], 1162 | params: CallParams, 1163 | toDs?: boolean 1164 | ): Promise { 1165 | if (this.walletProvider) { 1166 | // ugly hack for zilpay provider 1167 | const txn = await (contract as any).call(transition, args, params, toDs) 1168 | txn.id = txn.ID 1169 | txn.isRejected = function (this: { errors: any[]; exceptions: any[] }) { 1170 | return this.errors.length > 0 || this.exceptions.length > 0 1171 | } 1172 | return txn 1173 | } else { 1174 | return await contract.callWithoutConfirm(transition, args, params, toDs) 1175 | } 1176 | } 1177 | 1178 | public subscribeToAppChanges() { 1179 | // clear existing subscription, if any 1180 | this.subscription?.stop() 1181 | 1182 | const ziloContractHashes = Object.keys(this.zilos) 1183 | const subscription = this.zilliqa.subscriptionBuilder.buildEventLogSubscriptions(WSS[this.network], { 1184 | addresses: [this.contractHash, ...ziloContractHashes], 1185 | }) 1186 | 1187 | subscription.subscribe({ query: MessageType.NEW_BLOCK }) 1188 | 1189 | subscription.emitter.on(StatusType.SUBSCRIBE_EVENT_LOG, event => { 1190 | console.log('ws connected: ', event) 1191 | }) 1192 | 1193 | subscription.emitter.on(MessageType.NEW_BLOCK, event => { 1194 | // console.log('ws new block: ', JSON.stringify(event, null, 2)) 1195 | this.updateBlockHeight().then(() => this.updateObservedTxs()) 1196 | }) 1197 | 1198 | subscription.emitter.on(MessageType.EVENT_LOG, event => { 1199 | if (!event.value) return 1200 | // console.log('ws update: ', JSON.stringify(event, null, 2)) 1201 | this.updateAppState() 1202 | 1203 | // update zilo states 1204 | 1205 | const ziloAddresses = Object.keys(this.zilos) 1206 | if (!ziloAddresses.length) return 1207 | 1208 | // loop through events to find updates in registered zilos 1209 | for (const item of event.value) { 1210 | const byStr20Address = `0x${item.address}` 1211 | const index = ziloAddresses.indexOf(byStr20Address) 1212 | if (index >= 0) { 1213 | this.zilos[byStr20Address].updateZiloState() 1214 | 1215 | // remove updated zilo contract from list 1216 | ziloAddresses.splice(index, 1) 1217 | } 1218 | } 1219 | }) 1220 | 1221 | subscription.emitter.on(MessageType.UNSUBSCRIBE, event => { 1222 | console.log('ws disconnected: ', event) 1223 | this.subscription = null 1224 | }) 1225 | 1226 | subscription.start() 1227 | 1228 | this.subscription = subscription 1229 | } 1230 | 1231 | private async loadTokenList() { 1232 | if (this.network === Network.TestNet) { 1233 | this.tokens['ZIL'] = 'zil1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq9yf6pz' 1234 | this.tokens['wZIL'] = 'zil1nzn3k336xwal7egdzgalqnclxtgu3dggxed85m' 1235 | this.tokens['ZWAP'] = 'zil1k2c3ncjfduj9jrhlgx03t2smd6p25ur56cfzgz' 1236 | this.tokens['gZIL'] = 'zil1fytuayks6njpze00ukasq3m4y4s44k79hvz8q5' 1237 | this.tokens['SWTH'] = 'zil1d6yfgycu9ythxy037hkt3phc3jf7h6rfzuft0s' 1238 | this.tokens['XSGD'] = 'zil10a9z324aunx2qj64984vke93gjdnzlnl5exygv' 1239 | this.tokens['ZLP'] = 'zil1du93l0dpn8wy40769raza23fjkvm868j9rjehn' 1240 | this.tokens['PORT'] = 'zil10v5nstu2ff9jsm7074wer6s6xtklh9xga7n8xc' 1241 | this.tokens['REDC'] = 'zil14jmjrkvfcz2uvj3y69kl6gas34ecuf2j5ggmye' 1242 | this.tokens['STREAM'] = 'zil10w9gdtaau3d5uzqescshuqn9fd23gpa82myjqc' 1243 | this.tokens['zDAI'] = 'zil1nnga67uer2vk0harvu345vz7vl3v0pta6vr3sf' 1244 | this.tokens['zETH'] = 'zil1j53x0y8myrcpy6u4n42qe0yuxn5t2ttedah8jp' 1245 | return 1246 | } else if (this.network === Network.MainNet) { 1247 | this.tokens['ZIL'] = 'zil1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq9yf6pz' 1248 | this.tokens['wZIL'] = 'zil1gvr0jgwfsfmxsyx0xsnhtlte4gks6r3yk8x5fn' 1249 | } 1250 | 1251 | try { 1252 | const res = await fetch('https://api.zilstream.com/tokens') 1253 | const tokens = await res.json() 1254 | interface ZilStreamToken { 1255 | symbol: string 1256 | address_bech32: string 1257 | } 1258 | 1259 | tokens.forEach((token: ZilStreamToken) => (this.tokens[token.symbol] = token.address_bech32.split(',')[0])) 1260 | } catch (err) { 1261 | console.warn('WARNING: failed to load token list from zilstream, using defaults only.\nError: ' + err) 1262 | } 1263 | } 1264 | 1265 | private async updateBlockHeight(): Promise { 1266 | const response = await this.zilliqa.blockchain.getNumTxBlocks() 1267 | const bNum = parseInt(response.result!, 10) 1268 | this.currentBlock = bNum 1269 | 1270 | for (const ziloAddress of Object.keys(this.zilos)) { 1271 | // updateBlockHeight should only trigger update if 1272 | // contract state will be changed, i.e. only when 1273 | // currentBlock === zilo init.start_block or init.end_block. 1274 | await this.zilos[ziloAddress].updateBlockHeight(bNum) 1275 | } 1276 | } 1277 | 1278 | private async updateAppState(): Promise { 1279 | // Get user address 1280 | const currentUser = this.walletProvider 1281 | ? // ugly hack for zilpay provider 1282 | this.walletProvider.wallet.defaultAccount.base16.toLowerCase() 1283 | : this.zilliqa.wallet.defaultAccount?.address?.toLowerCase() || null 1284 | 1285 | // Get the contract state 1286 | const requests: BatchRequest[] = [] 1287 | const address = this.contractHash.replace('0x', '') 1288 | requests.push({ id: '1', method: 'GetSmartContractSubState', params: [address, 'output_after_fee', []], jsonrpc: '2.0' }) 1289 | requests.push({ id: '2', method: 'GetSmartContractSubState', params: [address, 'pools', []], jsonrpc: '2.0' }) 1290 | requests.push({ id: '3', method: 'GetSmartContractSubState', params: [address, 'total_contributions', []], jsonrpc: '2.0' }) 1291 | const result = await sendBatchRequest(this.rpcEndpoint, requests) 1292 | const contractState = Object.values(result).reduce((a, i) => ({ ...a, ...i }), { balances: {} }) as ContractState 1293 | 1294 | if (currentUser) { 1295 | const requests2: BatchRequest[] = [] 1296 | Object.keys(contractState.pools).forEach(token => { 1297 | requests2.push({ 1298 | id: token, 1299 | method: 'GetSmartContractSubState', 1300 | params: [address, 'balances', [token, currentUser]], 1301 | jsonrpc: '2.0', 1302 | }) 1303 | }) 1304 | const result2 = await sendBatchRequest(this.rpcEndpoint, requests2) 1305 | Object.entries(result2).forEach(([token, mapOrNull]) => { 1306 | contractState.balances[token] = mapOrNull ? mapOrNull.balances[token] : {} 1307 | }) 1308 | } 1309 | 1310 | // Get id of tokens that have liquidity pools 1311 | const poolTokenHashes = Object.keys(contractState.pools) 1312 | const defaultTokenHashes = Object.values(this.tokens).map((bech32: string) => this.getTokenAddresses(bech32).hash) 1313 | const tokenHashes = poolTokenHashes.concat(defaultTokenHashes.filter((item: string) => poolTokenHashes.indexOf(item) < 0)) 1314 | 1315 | // Get token details 1316 | const tokens: { [key in string]: TokenDetails } = {} 1317 | const promises = tokenHashes.map(async hash => { 1318 | try { 1319 | const d = await this.fetchTokenDetails(hash) 1320 | if (d === null) return 1321 | 1322 | tokens[hash] = d 1323 | } catch (err) { 1324 | if ( 1325 | (err as any).message?.startsWith('Could not retrieve contract init params') || 1326 | (err as any).message?.startsWith('Address not contract address') 1327 | ) { 1328 | return 1329 | } 1330 | throw err 1331 | } 1332 | }) 1333 | await Promise.all(promises) 1334 | 1335 | 1336 | // Get exchange rates 1337 | const pools: { [key in string]: Pool } = {} 1338 | tokenHashes.forEach(tokenHash => { 1339 | if (!contractState.pools[tokenHash]) return 1340 | 1341 | const [x, y] = contractState.pools[tokenHash]!.arguments 1342 | const zilReserve = new BigNumber(x) 1343 | const tokenReserve = new BigNumber(y) 1344 | const exchangeRate = zilReserve.dividedBy(tokenReserve) 1345 | const totalContribution = new BigNumber(contractState.total_contributions[tokenHash]!) 1346 | const poolBalances = contractState.balances[tokenHash] 1347 | const userContribution = new BigNumber(poolBalances && currentUser ? poolBalances[currentUser] || 0 : 0) 1348 | const contributionPercentage = userContribution.dividedBy(totalContribution).times(100) 1349 | 1350 | pools[tokenHash] = { 1351 | zilReserve, 1352 | tokenReserve, 1353 | exchangeRate, 1354 | totalContribution, 1355 | userContribution, 1356 | contributionPercentage, 1357 | } 1358 | }) 1359 | 1360 | 1361 | // Set new state 1362 | this.appState = { 1363 | contractState, 1364 | tokens, 1365 | pools, 1366 | currentUser, 1367 | currentNonce: this.appState?.currentNonce || null, 1368 | currentBalance: this.appState?.currentBalance || null, 1369 | } 1370 | } 1371 | 1372 | private async updateBalanceAndNonce() { 1373 | if (this.appState?.currentUser) { 1374 | try { 1375 | const res: RPCBalanceResponse = (await this.zilliqa.blockchain.getBalance(this.appState.currentUser)).result 1376 | if (!res) { 1377 | this.appState.currentBalance = new BigNumber(0) 1378 | this.appState.currentNonce = 0 1379 | return 1380 | } 1381 | this.appState.currentBalance = new BigNumber(res.balance) 1382 | this.appState.currentNonce = parseInt(res.nonce, 10) 1383 | } catch (err) { 1384 | // ugly hack for zilpay non-standard API 1385 | if ((err as any).message === 'Account is not created') { 1386 | this.appState.currentBalance = new BigNumber(0) 1387 | this.appState.currentNonce = 0 1388 | } 1389 | } 1390 | } 1391 | } 1392 | 1393 | private async updateObservedTxs() { 1394 | const release = await this.observerMutex.acquire() 1395 | try { 1396 | const removeTxs: string[] = [] 1397 | const promises = this.observedTxs.map(async (observedTx: ObservedTx) => { 1398 | try { 1399 | const result = await this.zilliqa.blockchain.getTransactionStatus(observedTx.hash) 1400 | 1401 | if (result && result.modificationState === 2) { 1402 | // either confirmed or rejected 1403 | const confirmedTxn = await this.zilliqa.blockchain.getTransaction(observedTx.hash) 1404 | const receipt = confirmedTxn.getReceipt() 1405 | const txStatus = confirmedTxn.isRejected() ? 'rejected' : receipt?.success ? 'confirmed' : 'rejected' 1406 | if (this.observer) this.observer(observedTx, txStatus, receipt) 1407 | removeTxs.push(observedTx.hash) 1408 | return 1409 | } 1410 | } catch (err) { 1411 | if ((err as any).code === -20) { 1412 | // "Txn Hash not Present" 1413 | console.warn(`tx not found in mempool: ${observedTx.hash}`) 1414 | } else { 1415 | console.warn('error fetching tx state') 1416 | console.error(err) 1417 | } 1418 | } 1419 | if (observedTx.deadline < this.currentBlock) { 1420 | // expired 1421 | console.log(`tx exceeded deadline: ${observedTx.deadline}, current: ${this.currentBlock}`) 1422 | if (this.observer) this.observer(observedTx, 'expired') 1423 | removeTxs.push(observedTx.hash) 1424 | } 1425 | }) 1426 | 1427 | await Promise.all(promises) 1428 | 1429 | this.observedTxs = this.observedTxs.filter((tx: ObservedTx) => !removeTxs.includes(tx.hash)) 1430 | 1431 | await this.updateBalanceAndNonce() 1432 | } finally { 1433 | release() 1434 | } 1435 | } 1436 | 1437 | private parseRecipientAddress(addr: string | null): string { 1438 | const address: string = addr === null ? this.getAppState().currentUser! : addr 1439 | if (address.substr(0, 2) === '0x') { 1440 | return address.toLowerCase() 1441 | } else if (address.length === 32) { 1442 | return `0x${address}`.toLowerCase() 1443 | } else if (address.substr(0, 3) === 'zil') { 1444 | return fromBech32Address(address).toLowerCase() 1445 | } else { 1446 | throw new Error('Invalid recipient address format!') 1447 | } 1448 | } 1449 | 1450 | private getTokenAddresses(id: string): { hash: string; address: string } { 1451 | let hash, address 1452 | 1453 | if (id.substr(0, 2) === '0x') { 1454 | hash = id.toLowerCase() 1455 | address = toBech32Address(hash) 1456 | } else if (id.substr(0, 3) === 'zil' && id.length > 3) { 1457 | address = id 1458 | hash = fromBech32Address(address).toLowerCase() 1459 | } else { 1460 | address = this.tokens[id] 1461 | hash = fromBech32Address(address).toLowerCase() 1462 | } 1463 | 1464 | return { hash, address } 1465 | } 1466 | 1467 | private getTokenDetails(id: string): TokenDetails { 1468 | const { hash } = this.getTokenAddresses(id) 1469 | if (!this.appState) { 1470 | throw new Error('App state not loaded, call #initialize first.') 1471 | } 1472 | if (!this.appState.tokens[hash]) { 1473 | throw new Error(`Could not find token details for ${id}`) 1474 | } 1475 | return this.appState.tokens[hash] 1476 | } 1477 | 1478 | public async fetchContractInit(contract: Contract): Promise { 1479 | // try to use cache first 1480 | const lsCacheKey = `contractInit:${contract.address!}` 1481 | if (isLocalStorageAvailable()) { 1482 | const result = localStorage.getItem(lsCacheKey) 1483 | if (result && result !== '""') { 1484 | try { 1485 | return JSON.parse(result) 1486 | } catch (e) { 1487 | console.error(e) 1488 | } 1489 | } 1490 | } 1491 | // motivation: workaround api.zilliqa.com intermittent connection issues. 1492 | try { 1493 | // some wallet providers throw an uncaught error when address is non-contract 1494 | const init = await new Zilliqa(this.rpcEndpoint).contracts.at(contract.address!).getInit() 1495 | if (init === undefined) throw new Error(`Could not retrieve contract init params ${contract.address}`) 1496 | if (!init) return null; 1497 | 1498 | if (isLocalStorageAvailable()) { 1499 | localStorage.setItem(lsCacheKey, JSON.stringify(init)) 1500 | } 1501 | return init 1502 | } catch (err) { 1503 | if ((err as any).message === 'Network request failed') { 1504 | // make another fetch attempt after 800ms 1505 | return this.fetchContractInit(contract) 1506 | } else { 1507 | throw err 1508 | } 1509 | } 1510 | } 1511 | 1512 | private async fetchTokenDetails(id: string): Promise { 1513 | const { hash, address } = this.getTokenAddresses(id) 1514 | 1515 | if (!!this.appState?.tokens[hash]) return this.appState.tokens[hash] 1516 | 1517 | const contract = this.getContract(address) 1518 | 1519 | if (hash === ZIL_HASH) { 1520 | return { contract, address, hash, name: 'Zilliqa', symbol: 'ZIL', decimals: 12, whitelisted: true, registered: true } 1521 | } 1522 | 1523 | const init = await this.fetchContractInit(contract) 1524 | if (init === null) return null 1525 | 1526 | const decimalStr = init.find((e: Value) => e.vname === 'decimals').value as string 1527 | const decimals = parseInt(decimalStr, 10) 1528 | const name = init.find((e: Value) => e.vname === 'name').value as string 1529 | const symbol = init.find((e: Value) => e.vname === 'symbol').value as string 1530 | const registered = this.tokens[symbol] === address 1531 | const whitelisted = registered && WHITELISTED_TOKENS[this.network].includes(address) 1532 | 1533 | return { contract, address, hash, name, symbol, decimals, whitelisted, registered } 1534 | } 1535 | 1536 | private async checkAllowedBalance(token: TokenDetails, amount: BigNumber) { 1537 | // Check init 1538 | this.checkAppLoadedWithUser() 1539 | const user = this.appState!.currentUser! 1540 | 1541 | if (token.hash === ZIL_HASH) { 1542 | // Check zil balance 1543 | const zilBalance = this.appState!.currentBalance! 1544 | if (zilBalance.lt(amount)) { 1545 | throw new Error(`Insufficent ZIL in wallet. 1546 | Required: ${this.toUnit(token.hash, amount.toString()).toString()}, 1547 | have: ${this.toUnit(token.hash, zilBalance.toString()).toString()}.`) 1548 | } 1549 | } else { 1550 | // Check zrc-2 balance 1551 | const requests: BatchRequest[] = [] 1552 | const address = token.contract.address!.replace('0x', '') 1553 | requests.push({ id: 'balances', method: 'GetSmartContractSubState', params: [address, 'balances', [user!]], jsonrpc: '2.0' }) 1554 | requests.push({ 1555 | id: 'allowances', 1556 | method: 'GetSmartContractSubState', 1557 | params: [address, 'allowances', [user!, this.contractHash]], 1558 | jsonrpc: '2.0', 1559 | }) 1560 | const result = await sendBatchRequest(this.rpcEndpoint, requests) 1561 | const balance = new BigNumber(result.balances?.balances[user] || 0) 1562 | if (balance.lt(amount)) { 1563 | throw new Error(`Insufficent tokens in wallet. 1564 | Required: ${this.toUnit(token.hash, amount.toString()).toString()}, 1565 | have: ${this.toUnit(token.hash, balance.toString()).toString()}.`) 1566 | } 1567 | const allowance = new BigNumber(result.allowances?.allowances[user]?.[this.contractHash] || 0) 1568 | if (allowance.lt(amount)) { 1569 | throw new Error(`Tokens need to be approved first. 1570 | Required: ${this.toUnit(token.hash, amount.toString()).toString()}, 1571 | approved: ${this.toUnit(token.hash, allowance.toString()).toString()}.`) 1572 | } 1573 | } 1574 | } 1575 | 1576 | public checkAppLoadedWithUser() { 1577 | // Check init 1578 | if (!this.appState) { 1579 | throw new Error('App state not loaded, call #initialize first.') 1580 | } 1581 | 1582 | // Check user address 1583 | if (this.appState!.currentUser === null) { 1584 | throw new Error('No wallet connected.') 1585 | } 1586 | 1587 | // Check wallet account 1588 | if (this.walletProvider && this.walletProvider.wallet.defaultAccount.base16.toLowerCase() !== this.appState!.currentUser) { 1589 | throw new Error('Wallet user has changed, please reconnect.') 1590 | } 1591 | 1592 | // Check network is correct 1593 | if (this.walletProvider && this.walletProvider.wallet.net.toLowerCase() !== this.network.toLowerCase()) { 1594 | throw new Error('Wallet is connected to wrong network.') 1595 | } 1596 | } 1597 | 1598 | public txParams(): TxParams & { nonce: number } { 1599 | return { 1600 | nonce: this.nonce(), 1601 | ...this._txParams, 1602 | } 1603 | } 1604 | 1605 | public getCurrentBlock(): number { 1606 | return this.currentBlock 1607 | } 1608 | 1609 | public deadlineBlock(): number { 1610 | return this.currentBlock + this.deadlineBuffer! 1611 | } 1612 | 1613 | private nonce(): number { 1614 | return this.appState!.currentNonce! + this.observedTxs.length + 1 1615 | } 1616 | 1617 | private validateMaxExchangeRateChange(maxExchangeRateChange: number) { 1618 | if (maxExchangeRateChange % 1 !== 0 || maxExchangeRateChange >= BASIS || maxExchangeRateChange < 0) { 1619 | throw new Error(`MaxExchangeRateChange ${maxExchangeRateChange} must be an integer between 0 and ${BASIS + 1}.`) 1620 | } 1621 | } 1622 | } 1623 | --------------------------------------------------------------------------------