diff --git a/README.md b/README.md index 06dcc87..dc27dd5 100644 --- a/README.md +++ b/README.md @@ -1,123 +1,8 @@ # Tokenlon MMSK -Market maker server kit, for tokenlon's MM(Market Maker). +Market Maker Service Kit. -See [docs](https://docs.token.im/tokenlon-mmsk/) - -## Setup - -Require Node.JS v12 as runtime. - -Program setup, -- Create a wallet as order signer, and save it as keystore or private key -- Deploy market maker proxy contract on ethereum - - with several permissions setting, such as token allowance, withdrawal account - - deposit token asset to contract -- Implement a market maker backend http server - - see Quoter interface, mostly quote with (buy, sell, amount) returning a price number -- Modify the options in `app/mmConfig.js`, including, - - EXCHANGE_URL, point to tokenlon exchange server - - PROVIDER_URL, point to ethereum node, like your infura endpoint - - PERMIT_TYPE, approve tokens to `RFQv2` contract directly or approve tokens to `AllowanceTarget` contract. - - WALLET_ADDRESS, as your signer wallet address - - WALLET_PRIVATE_KEY, private key of above wallet, or use WALLET_KEYSTORE - - WALLET_TYPE, a market maker's wallet smart contract. - - types.WalletType.MMP_VERSION_4 (compatible with PMM protocol, see [example contract](https://gist.github.com/NIC619/a3db1a743175bf592f2db983f17680dd#file-mmpv4-sol-L1236)) - - types.WalletType.MMP_VERSION_5 - - types.WalletType.ERC1271 - - types.WalletType.EOA - - SIGNING_URL, If you wanna sign orders in your own service instead of the mmsk, - please set the SIGNING_URL to your service endpoint. the mmsk would post every unsigned PMM/RFQV1/RFQV2 orders to your service. Remember to set the WALLET_ADDRESS as well. Example PMMV5/RFQV1/RFQV2 requests are shown below: - - PMMV5: - ``` - { - quoteId: '0x123', - protocol: 'PMMV5', - pmmOrder: { - makerAddress: '0x86b9f429c3ef44c599eb560eb531a0e3f2e36f64', - makerAssetAmount: '100000000', - makerAssetData: '0xf47261b0000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7', - makerFee: '0', - takerAddress: '0x7bd7d025d4231aad1233967b527ffd7416410257', - takerAssetAmount: '1000000000000000000', - takerAssetData: '0xf47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - takerFee: '0', - senderAddress: '0x7bd7d025d4231aad1233967b527ffd7416410257', - feeRecipientAddress: '0x8fba2dd6968ddc51aea563091008d8451fec4db6', - expirationTimeSeconds: '1620444917', - exchangeAddress: '0x86b9f429c3ef44c599eb560eb531a0e3f2e36f64', - salt: '22685491128062564230891640495451214097' - }, - feeFactor: 30, - orderHash: '0x9f9bb186d77c19a763266f54978eef923f3e6ebd5ac6d2c687b1323abe91d8b5', - orderSignDigest: '0x6e95144f3539f8679b94e858a0bcd755e8b17a4011e2fdf025387e4523a9b0fe', - userAddr: '0x8fba2dd6968ddc51aea563091008d8451fec4db6', - chainId: 1, - pmmAddr: '0x7bd7d025D4231aAD1233967b527FFd7416410257' - } - ``` - - RFQV1: - ``` - { - quoteId: '0x123', - protocol: 'RFQV1', - rfqOrder: { - takerAddr: '0xcabfea3a7f41452a9c8e475a53b30c43fbff6683', - makerAddr: '0x86b9f429c3ef44c599eb560eb531a0e3f2e36f64', - takerAssetAddr: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - makerAssetAddr: '0xdac17f958d2ee523a2206206994597c13d831ec7', - takerAssetAmount: '1000000000000000000', - makerAssetAmount: '100000000', - deadline: 1620444917, - feeFactor: 30, - salt: '7719472615821079694904732333912527190235994441565629342017219118620679208990' - }, - feeFactor: 30, - orderHash: '0x77eda617afe88090a34cf031470b0968c1754a474f573dfb5c5b5c67cf8167ce', - orderSignDigest: '0xdd785ffa1a694db8af972523ee115fc95580929e23ac5c46a62692b0f6600fc5', - userAddr: '0xcabfea3a7f41452a9c8e475a53b30c43fbff6683', - chainId: 1, - rfqAddr: '0x117CAf73eB142eDC431E707DC33D4dfeF7c5BAd0' - } - ``` - - RFQV2: - ``` - { - quoteId: '0x123', - protocol: 'RFQV2', - rfqOrder: { - taker: '0x8fda8bc038af1c426838248718eb2fd5425882cc', - maker: '0x86b9f429c3ef44c599eb560eb531a0e3f2e36f64', - takerToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - takerTokenAmount: '1000000000000000000', - makerToken: '0xdac17f958d2ee523a2206206994597c13d831ec7', - makerTokenAmount: '100000000', - feeFactor: '30', - expiry: '1620444917', - salt: '0x11111111111111111111111111111111' - }, - feeFactor: 30, - orderHash: '0xd431d9a453b67d76244e6ea1244895fa4c2e874eee03bc2af1f6e171afa938ae', - orderSignDigest: '0x9573a91c47d9bdad67354a5a677d778eff3ccb94866bfe3c2907827db7866c91', - userAddr: '0x8fda8bc038af1c426838248718eb2fd5425882cc', - chainId: 1, - rfqAddr: '0xaE5FDd548E5B107C54E5c0D36952fB8a089f10C7' - } - ``` - - An example response the signing service should return - ``` - { - signature: "0x122344..." - } - ``` - - HTTP_SERVER_ENDPOINT, your backend http quoting server - - CHAIN_ID, 1 for mainnet, 5 for testnet(Goerli) -- Testing with `node app/check.js` -- Register contract address, signer address and MMSK server url to Tokenlon team +See [docs](/docs/index.md) ## Version Release diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..9ce0f39 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,114 @@ +## Configuration + +Require Node.JS v12 or above as runtime. + +Program setup, +- Create a wallet as order signer, and save it as keystore or private key +- Deploy market maker proxy contract on ethereum + - with several permissions setting, such as token allowance, withdrawal account + - deposit token asset to contract +- Implement a market maker backend http server + - see [interfaces](interfaces.md), mostly quote with (buy, sell, amount) returning a price number +- Modify the options in `app/mmConfig.js`, including, + - EXCHANGE_URL, point to tokenlon exchange server + - PROVIDER_URL, point to ethereum node, like your infura endpoint + - HTTP_SERVER_ENDPOINT, your backend http quoting server. See [interfaces](interfaces.md) + - CHAIN_ID, 1 for mainnet, 5 for testnet(Goerli) + - PERMIT_TYPE, approve tokens to `RFQv2` protocol contract directly or approve tokens to `AllowanceTarget` contract for PMMV5/RFQV1 protocols. + - WALLET_ADDRESS, as your signer wallet address + - WALLET_PRIVATE_KEY, private key of above wallet, or use WALLET_KEYSTORE + - WALLET_TYPE, a type of market making wallet contract. + - types.WalletType.MMP_VERSION_4 (see [example contract](https://gist.github.com/NIC619/a3db1a743175bf592f2db983f17680dd#file-mmpv4-sol-L1236)) + - types.WalletType.ERC1271_EIP712: your market making contract could verify standard EIP712 signatures. + - types.WalletType.ERC1271_EIP712_EIP191: your market making contract could verify signatures correspond to the digest of EIP712 struct hash with a EIP191 prefix. + - types.WalletType.EOA + - SIGNING_URL, If you wanna sign orders in your own service instead of the mmsk, + please set the SIGNING_URL to your service endpoint. the mmsk would post every unsigned PMMV5/RFQV1/RFQV2 orders to your service. Remember to set the WALLET_ADDRESS as well. Example PMMV5/RFQV1/RFQV2 requests are shown below: + + PMMV5: + ``` + { + quoteId: '0x123', + protocol: 'PMMV5', + pmmOrder: { + makerAddress: '0x86b9f429c3ef44c599eb560eb531a0e3f2e36f64', + makerAssetAmount: '100000000', + makerAssetData: '0xf47261b0000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7', + makerFee: '0', + takerAddress: '0x7bd7d025d4231aad1233967b527ffd7416410257', + takerAssetAmount: '1000000000000000000', + takerAssetData: '0xf47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + takerFee: '0', + senderAddress: '0x7bd7d025d4231aad1233967b527ffd7416410257', + feeRecipientAddress: '0x8fba2dd6968ddc51aea563091008d8451fec4db6', + expirationTimeSeconds: '1620444917', + exchangeAddress: '0x86b9f429c3ef44c599eb560eb531a0e3f2e36f64', + salt: '22685491128062564230891640495451214097' + }, + feeFactor: 30, + orderHash: '0x9f9bb186d77c19a763266f54978eef923f3e6ebd5ac6d2c687b1323abe91d8b5', + orderSignDigest: '0x6e95144f3539f8679b94e858a0bcd755e8b17a4011e2fdf025387e4523a9b0fe', + userAddr: '0x8fba2dd6968ddc51aea563091008d8451fec4db6', + chainId: 1, + pmmAddr: '0x7bd7d025D4231aAD1233967b527FFd7416410257' + } + ``` + + RFQV1: + ``` + { + quoteId: '0x123', + protocol: 'RFQV1', + rfqOrder: { + takerAddr: '0xcabfea3a7f41452a9c8e475a53b30c43fbff6683', + makerAddr: '0x86b9f429c3ef44c599eb560eb531a0e3f2e36f64', + takerAssetAddr: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + makerAssetAddr: '0xdac17f958d2ee523a2206206994597c13d831ec7', + takerAssetAmount: '1000000000000000000', + makerAssetAmount: '100000000', + deadline: 1620444917, + feeFactor: 30, + salt: '7719472615821079694904732333912527190235994441565629342017219118620679208990' + }, + feeFactor: 30, + orderHash: '0x77eda617afe88090a34cf031470b0968c1754a474f573dfb5c5b5c67cf8167ce', + orderSignDigest: '0xdd785ffa1a694db8af972523ee115fc95580929e23ac5c46a62692b0f6600fc5', + userAddr: '0xcabfea3a7f41452a9c8e475a53b30c43fbff6683', + chainId: 1, + rfqAddr: '0x117CAf73eB142eDC431E707DC33D4dfeF7c5BAd0' + } + ``` + + RFQV2: + ``` + { + quoteId: '0x123', + protocol: 'RFQV2', + rfqOrder: { + taker: '0x8fda8bc038af1c426838248718eb2fd5425882cc', + maker: '0x86b9f429c3ef44c599eb560eb531a0e3f2e36f64', + takerToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + takerTokenAmount: '1000000000000000000', + makerToken: '0xdac17f958d2ee523a2206206994597c13d831ec7', + makerTokenAmount: '100000000', + feeFactor: '30', + expiry: '1620444917', + salt: '0x11111111111111111111111111111111' + }, + feeFactor: 30, + orderHash: '0xd431d9a453b67d76244e6ea1244895fa4c2e874eee03bc2af1f6e171afa938ae', + orderSignDigest: '0x9573a91c47d9bdad67354a5a677d778eff3ccb94866bfe3c2907827db7866c91', + userAddr: '0x8fda8bc038af1c426838248718eb2fd5425882cc', + chainId: 1, + rfqAddr: '0xaE5FDd548E5B107C54E5c0D36952fB8a089f10C7' + } + ``` + + An example response the signing service should return + ``` + { + signature: "0x122344..." + } + ``` +- Testing with `node app/check.js` +- Register contract address, signer address and MMSK server url to Tokenlon team \ No newline at end of file diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..89ac8d8 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,11 @@ +# Tokenlon Market Maker Service Kit + +## Introduction + +**Tokenlon-MMSK** is a tool to start nodejs http service for market making. The service is deployed on the market maker side. It is an intermediate proxy that connects the Tokenlon Server and the market maker service. MMSK stands for **Market Maker Service Kit**, which is used to reduce the cost of communication at both ends. + +- [Installation](installation.md) +- [Preparation](preparation.md) +- [Configuration](configuration.md) +- [Interfaces](interfaces.md) +- [MMSK APIs](mmsk-api.md) diff --git a/docs/installation.md b/docs/installation.md new file mode 100755 index 0000000..39979f8 --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,8 @@ +# Installation +Download the latest [release here](https://github.com/consenlabs/tokenlon-mmsk/releases). + +To be sure that the file **hasn’t** been tampered with, we suggest the market maker checks the downloaded zip file’s sha256 checksum, for example via: `shasum -a 256 /path/to/file` + +After the check and un-zip is completed, enter the tokenlon-mmsk root directory, and execute: + +`yarn` or `npm install` diff --git a/docs/interfaces.md b/docs/interfaces.md new file mode 100644 index 0000000..3769b61 --- /dev/null +++ b/docs/interfaces.md @@ -0,0 +1,283 @@ +# Interfaces for Market-Makers + +The market maker needs to implement following 5 **Tokenlon-MMSK** interfaces: + +1. The pairs interface asks market maker for authorized trading currency pairs +2. The indicativePrice interface asks market maker to provide a reference price for a specific trading currency pair +3. The price interface asks the market maker quoting prices for a specific trading amount +4. The deal interface: Once the quote confirmed by the users, the Tokenlon Server will push an order to the MMSK, and MMSK then notifies the market maker via the deal interface +5. The exception interface: Once the order has some exception situation, the Tokenlon Server will push an exception order to the MMSK, and MMSK then notifies the market maker via the exception interface + +## HTTP approach + +### pairs interface + +> Request + +```bash +curl 'HTTP_SERVER_ENDPOINT/pairs' +``` + +> Response + +```json +// Returned in normal conditions +{ + "result": true, + "pairs": [ + "SNT/ETH", + "OMG/ETH", + "DAI/ETH" + ] +} + +// Returned in other circumstances +{ + "result": false, + "message": "Exception" +} +``` + +Request address: `HTTP_SERVER_ENDPOINT/pairs` + + + +#### Parameter +GET + +#### return +none + +#### request return + + +##### Returned in normal conditions + +|Name|Type|Description| +|----|----|----| +|result|Boolean|whether normal return| +|pairs|Array|pair string array| + +##### Returned in other circumstances +|Name|Type|Description| +|----|----|----| +|result|Boolean|whether normal return| +|message|String|possible error information| + +### indicativePrice interface + +> Request + +```bash +curl 'HTTP_SERVER_ENDPOINT/indicativePrice?base=SNT"e=OMG&amount=30&side=BUY' +``` + +> Response + +```json +// Returned in normal conditions +{ + "result": true, + "exchangeable": true, + "price": 0.00017508, + "minAmount": 0.0002, + "maxAmount": 100 +} + +// Returned in other circumstances +{ + "result": false, + "exchangeable": false, + "minAmount": 0.0002, + "maxAmount": 100, + "message": "insufficient balance" +} +``` + +Request URL: `HTTP_SERVER_ENDPOINT/indicativePrice` + + + +#### Request return +GET + +#### Request parameters +|Name|Type|Mandatory|Description| +|----|----|----|----| +|base|String|YES|base symbol| +|quote|String|YES|quote symbol| +|side|String|YES|'BUY' or 'SELL'| +|amount|Number|**NO**|**BUY** or **SELL** base amount| + +#### Request return + +##### Returned in normal conditions +|Name|Type|Description| +|----|----|----| +|result|Boolean|whether normal return| +|exchangeable|Boolean|Whether is tradable| +|minAmount|Number|The minimum amount that base token can be traded| +|maxAmount|Number|The maximum amount that base token can be traded| +|price|Number|| + +##### Returned in other circumstances +|Name|Type|Description| +|----|----|----| +|result|Boolean|whether normal return| +|exchangeable|Boolean|Whether is tradable| +|minAmount|Number|The minimum amount that base token can be traded| +|maxAmount|Number|The maximum amount that base token can be traded| +|message|String|possible error information| + + + +### price interface + +> Request + +```bash +curl 'HTTP_SERVER_ENDPOINT/price?base=SNT"e=OMG&amount=30&side=BUY&uniqId=dfdsfjsidf' +``` + +> Response + +```json +// Returned in normal conditions +{ + "result": true, + "exchangeable": true, + "price": 0.00017508, + "minAmount": 0.0002, + "maxAmount": 100, + "quoteId": "asfadsf-dsfsdf-ggsd-qwe-rgjty" +} + +// Returned in other circumstances +{ + "result": false, + "exchangeable": false, + "minAmount": 0.0002, + "maxAmount": 100, + "message": "insufficient balance" +} +``` + +Request URL: `HTTP_SERVER_ENDPOINT/price` + + + +#### Request return +GET + +#### Request parameters +|Name|Type|Mandatory|Description| +|----|----|----|----| +|base|String|YES|base symbol| +|quote|String|YES|quote symbol| +|side|String|YES|'BUY' or 'SELL'| +|amount|Number|**YES**|**BUY** or **SELL** base amount| +|uniqId|String|**YES**|Identifies each unique user| + +#### Request return + +##### Returned in normal conditions +|Name|Type|Description| +|----|----|----| +|result|Boolean|whether normal return| +|exchangeable|Boolean|Whether is tradable| +|minAmount|Number|The minimum amount that base token can be traded| +|maxAmount|Number|The maximum amount that base token can be traded| +|price|Number|| +|quoteId|String|A unique value used to track the final order of the quotation and the transaction status.| + +##### Returned in other circumstances +|Name|Type|Description| +|----|----|----| +|result|Boolean|whether normal return| +|exchangeable|Boolean|Whether is tradable| +|minAmount|Number|The minimum amount that base token can be traded| +|maxAmount|Number|The maximum amount that base token can be traded| +|message|String|possible error information| + +### deal interface + +> Request + +```bash +curl -X POST \ + HTTP_SERVER_ENDPOINT/deal \ + -H 'Content-Type: application/json' \ + -H 'cache-control: no-cache' \ + -d '{"makerToken": "SNT","takerToken":"OMG","makerTokenAmount":30,"takerTokenAmount":0.1,"quoteId":"234dsfasd-sdfasdf-sdfasf","timestamp":1231234324}' +``` + +> Response + +```json +{ + "result": true +} +``` + +Request address: `HTTP_SERVER_ENDPOINT/deal` + +#### Request return +POST + +#### Request parameters +|Name|Type|Mandatory|Description| +|----|----|----|----| +|makerToken|String|YES|token symbol| +|takerToken|String|YES|token symbol| +|makerTokenAmount|Number|YES|maker token's amount| +|takerTokenAmount|Number|YES|taker token's amount| +|quoteId|String|YES|quoteId from price interface| +|timestamp|Number|YES|| + +#### Request return +|Name|Type|Description| +|----|----|----| +|result|Boolean|We suggest you just return `true`, If you return `false`,imToken will always retry to send this notification to you, and it maybe repeat your hedge.| + + +### exception interface + +> Request + +```bash +curl -X POST \ + HTTP_SERVER_ENDPOINT/exception \ + -H 'Content-Type: application/json' \ + -H 'cache-control: no-cache' \ + -d '{"makerToken": "SNT","takerToken":"OMG","makerTokenAmount":30,"takerTokenAmount":0.1,"quoteId":"234dsfasd-sdfasdf-sdfasf","timestamp":1231234324,"type":"FAILED"}' +``` + +> Response + +```json +{ + "result": true +} +``` + +#### Parameter +|Name|Type|Mandatory|Description| +|----|----|----|----| +|makerToken|String|YES|token symbol| +|takerToken|String|YES|token symbol| +|makerTokenAmount|Number|YES|maker token's amount| +|takerTokenAmount|Number|YES|taker token's amount| +|quoteId|String|YES|quoteId from price interface| +|type|String|YES|'FAILED' means that order failed; 'TIMEOUT' means that order timeout(also failed too);'DELAY' means that order is executed but Tokenlon didn't notify MM by deal API | +|timestamp|Number|YES|| + +#### return +|Name|Type|Description| +|----|----|----| +|result|Boolean|We suggest you just return `true`, **If you return `false`,imToken will always retry to send this notification to you, and it maybe repeat your processing.| \ No newline at end of file diff --git a/docs/mmsk-api.md b/docs/mmsk-api.md new file mode 100755 index 0000000..55049b2 --- /dev/null +++ b/docs/mmsk-api.md @@ -0,0 +1,443 @@ +# Public API provided by MMSK + +**tokenlon-mmsk** also provides following public APIs to marker makers. + +## getSupportedTokenList + +> example + +```json +{ + "result": true, + "tokens": [ + { + "symbol": "ETH", + "opposites": [ + "MANA", + "SNT", + ] + }, + { + "symbol": "MANA", + "opposites": [ + "ETH" + ] + }, + { + "symbol": "SNT", + "opposites": [ + "ETH" + ] + } + ] +} +``` + +Tokenlon will return the tokens supported by the market maker and Tokenlon through this interface, through the pairs interface of the market maker and the `getTokenList` interface of Tokenlon Server. + +#### Request mode +GET + +#### Request parameter +None + +#### request return +|Name|Type|Description| +|----|----|----| +|result|Boolean|Whether Returned in normal conditions| +|tokens|Array| token item array| + +## getRate + +> example + +```json +{ + "result": true, + "exchangeable": true, + "minAmount": 0.0002, + "maxAmount": 100, + "rate": 124.28 +} +``` + +Tokenlon Server will continuously poll the `getRate` interface of the requesting market maker mmsk Server to provide the best quotation to the user. This interface is only a simple derivative of the market maker's indicativePrice interface. + +#### Request mode +GET + +#### Request parameters +|Name|Type|Mandatory|description| +|----|----|----|----| +|base|String|YES|base symbol| +|quote|String|YES|quote symbol| +|side|String|YES|'BUY' or 'SELL'| +|amount|Number|**NO**|**BUY** or **SELL** base amount| + +#### request return +#### Returned in normal conditions +|Name|Type|description| +|----|----|----| +|result|Boolean|Whether Returned in normal conditions| +|exchangeable|Boolean|Whether is tradable| +|minAmount|Number|The minimum amount that base token can be traded| +|maxAmount|Number|The maximum amount that base token can be traded| +|rate|Number|| + +#### Returned in other circumstances +|Name|Type|Description| +|----|----|----| +|result|Boolean|Whether Returned in normal conditions| +|exchangeable|Boolean|Whether is tradable| +|minAmount|Number|The minimum amount that base token can be traded| +|maxAmount|Number|The maximum amount that base token can be traded| +|message|String|error message| + +## newOrder + +> example + +```json +{ + "result": true, + "rate": 0.00002, + "exchangeable": true, + "minAmount": 0.0002, + "maxAmount": 100, + "order": { + "makerAddress": "0xb6025914f4e631d458f4668cc232d1e38ddbd569", + "makerAssetAmount": "1000000000000000000000", + "makerAssetData": "0xf47261b0000000000000000000000000744d70fdbe2ba4cf95131626614a1763df805b9e", + "makerFee": "0", + "takerAddress": "0x08053129c3967f4a496958aac5a1e8e6df6c7652", + "takerAssetAmount": "23324453240000000000", + "takerAssetData": "0xf47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + "takerFee": "0", + "senderAddress": "0x8f19bf4b5dfae80c1e3f91bd33f3bbc37326d5e7", + "feeRecipientAddress": "0x0000000000000000000000000000000000000000", + "expirationTimeSeconds": "1539498614", + "exchangeAddress": "0x2002d3812f58e35f0ea1ffbf80a75a38c32175fa", + "salt": "59572482685924225672407231424301404205239289582722616080644908172098386763718", + "makerWalletSignature": "0x1b66353b9b6cff19d5acbdf275d55e988c2a077c6c6074bcf49705e09b7efd3a61212821ff244b96623fa5181507da0b796a6693b1d511e9355a83c4c06ac88a66fba2ff8436171ddd3653cd2ca1c5595046144d7f04", + "quoteId": "TD-190109-173025-NqGaWun", + "feeFactor": 10 + } +} +``` + +When the user clicks quote request button in the imToken app, they will get the order for the corresponding price. The Tokenlon server polls the newOrder interface of each market maker’s **mmsk server** to provide the order with the best quote prices to the user. + + +#### Request mode +GET + +#### Request parameters +|Name|Type|Mandatory|description| +|----|----|----|----| +|base|String|YES|base symbol| +|quote|String|YES|quote symbol| +|side|String|YES|'BUY' or 'SELL'| +|userAddr|String|YES|user's address| +|amount|Number|**YES**|**BUY** or **SELL** base amount| +|uniqId|String|**YES**|represents the user's unique Id| + +#### request return + +#### Returned in normal conditions +|Name|Type|description| +|----|----|----| +|result|Boolean|Whether Returned in normal conditions| +|exchangeable|Boolean|Whether is tradable| +|minAmount|Number|The minimum amount that base token can be traded| +|maxAmount|Number|The maximum amount that base token can be traded| +|rate|Number|This order's rate| +|order|Object| 0x's maker signed order| + +#### Returned in other circumstances +|Name|Type|Description| +|----|----|----| +|result|Boolean|Whether Returned in normal conditions| +|exchangeable|Boolean|Whether is tradable| +|minAmount|Number|The minimum amount that base token can be traded| +|maxAmount|Number|The maximum amount that base token can be traded| +|message|String|error message| + +## dealOrder + +> example + +```ts +{ + makerToken: 'SNT', + takerToken: 'ETH', + makerTokenAmount: 1000, + takerTokenAmount: 1, + quoteId: '234dsfasd-sdfasdf-sdfasf', + timestamp: 1231234324, +} +``` + +#### Request mode +POST + +#### Request parameters +|Name|Type|Mandatory|Description| +|----|----|----|----| +|makerToken|String|YES|token symbol| +|takerToken|String|YES|token symbol| +|makerTokenAmount|Number|YES|maker token's amount| +|takerTokenAmount|Number|YES|taker token's amount| +|quoteId|String|YES|quoteId from price interface| +|timestamp|Number|YES|| + +#### request return + +#### Returned in normal conditions +|Name|Type|description| +|----|----|----| +|result|true|| + +#### Returned in other circumstances +|Name|Type|Description| +|----|----|----| +|result|false|| +|message|String|error message| + + +## exceptionOrder + +> example + +```ts +{ + makerToken: 'SNT', + takerToken: 'ETH', + makerTokenAmount: 1000, + takerTokenAmount: 1, + quoteId: '234dsfasd-sdfasdf-sdfasf', + timestamp: 1231234324, + type: 'FAILED', +} +``` + +#### Request parameters +POST + +#### Request parameters +|Name|Type|Mandatory|Description| +|----|----|----|----| +|makerToken|String|YES|token symbol| +|takerToken|String|YES|token symbol| +|makerTokenAmount|Number|YES|maker token's amount| +|takerTokenAmount|Number|YES|taker token's amount| +|quoteId|String|YES|quoteId from price interface| +|type|String|YES|'FAILED': the order transaction failed to execute on-chain;'TIMEOUT' means the order was expired;'DELAY' if an order executed on-chain, but Tokenlon server never sent the corresponding deal signal to the market maker. Should investigate the transaction ASAP. +|timestamp|Number|YES|| + +#### request return + +#### Returned in normal conditions +|Name|Type|description| +|----|----|----| +|result|true|| + +#### Returned in other circumstances +|Name|Type|Description| +|----|----|----| +|result|false|| +|message|String|error message | + + +## version +#### Request mode +GET + +#### request return +|Name|Type|description| +|----|----|----| +|result|true|| +|version|String|The version of MMSK| + + +## getBalance + +> example + +```json +{ + "result": true, + "balance": 0.13371396 +} +``` + +Market maker can get `marketMakerProxyContract` contract’s corresponding token balance through this interface. + +#### Request mode +GET + +#### Request parameters +|Name|Type|Mandatory|description| +|----|----|----|----| +|token|String|YES|token symbol| + +#### request return +|Name|Type|description| +|----|----|----| +|result|Boolean|Whether Returned in normal conditions| +|balance|Number|the token's balance| + +## getBalances + +> example + +```json +{ + "result": true, + "balances": [ + { + "symbol": "ETH", + "balance": 0.13371396 + }, + { + "symbol": "ZRX", + "balance": 0 + }, + { + "symbol": "DAI", + "balance": 5.78464455 + }, + { + "symbol": "KNC", + "balance": 49.99451026 + }, + { + "symbol": "MKR", + "balance": 0 + }, + { + "symbol": "OMG", + "balance": 0 + }, + { + "symbol": "SNT", + "balance": 0 + }, + { + "symbol": "MANA", + "balance": 0 + } + ] +} +``` + + +Same as getBalance, but can get multiple balances. The market maker can get token balances of multiple `marketMakerProxyContract` contract through this interface. + + + + +#### Request mode +GET + +#### Request parameters +无 + +#### request return +|Name|Type|description| +|----|----|----| +|result|Boolean|Whether Returned in normal conditions| +|balances|Array|balance item array| + +## getOrdersHistory + +> example + +```json +{ + "result": true, + "orders": [ + { + "makerToken": "SNT", + "takerToken": "ETH", + "makerTokenAmount": 1000, + "takerTokenAmount": 1, + "quoteId": "234dsfasd-sdfasdf-sdfasf", + "status": "success", + "txHash": "0x953e9641811865e2a5da0bcfbee1c0da2f88e252efb9e782e60730ac0e730807", + "timestamp": 1549349662 + } + ] +} +``` + +The Market Maker can get the order of all transactions through this interface. + +#### Request mode +GET + +#### Request parameters +|Name|Type|Mandatory|description| +|----|----|----|----| +|page|Number|YES|| +|perpage|Number|YES|per page| + +#### request return +|Name|Type|description| +|----|----|----| +|result|Boolean|Whether Returned in normal conditions| +|orders|Array|See the example| + +## getOrderState + +> example + +```json +{ + "result": true, + "order": { + "makerToken": "SNT", + "takerToken": "ETH", + "makerTokenAmount": 1000, + "takerTokenAmount": 1, + "quoteId": "234dsfasd-sdfasdf-sdfasf", + "status": "success", + "txHash": "0x953e9641811865e2a5da0bcfbee1c0da2f88e252efb9e782e60730ac0e730807", + "timestamp": 1549349662 + } +} +``` + +The Market Maker can get the order status of each transaction by quoteId through this interface. + +#### Request mode +GET + +#### Request parameters +|Name|Type|Mandatory|description| +|----|----|----|----| +|quoteId|String|YES|a unique value final order for tracking the offer, and if transaction| + +#### request return +|Name|Type|description| +|----|----|----| +|result|Boolean|Whether Returned in normal conditions| +|order|Object|See the example| + +## Appendix:order status +**corresponding `status` to an `order` can be:** + +|status|description| +|----|----| +|unbroadcast | Order has not been forwarded by the service to the chain| +|pending | Transaction is in mempool, waiting to be mined| +|success | Successfully submitted on chain | +|failed | Failure of on-chain transaction| +|timeout | Timeout of transaction on chain| +|invalid | Order is invalid| +|abandoned| Order isn't be used| + + \ No newline at end of file diff --git a/docs/preparation.md b/docs/preparation.md new file mode 100755 index 0000000..4d84910 --- /dev/null +++ b/docs/preparation.md @@ -0,0 +1,6 @@ +# Preparation + +1. The market maker needs to prepare a wallet for signature, the **marketMakerSigner** +2. Contact Tokenlon and provide the **signing EOA** wallet address and your existing market making wallet contract to Tokenlon. if you don't have one, Tokenlon will deploy a **MarketMakerProxyContract** for you. +3. Contact Tokenlon for environment parameters such as `EXCHANGE_URL` +4. Deposit tokens to your **market making contract wallet**