@stellar-broker/client 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/lib/stellarbroker.js +1 -1
- package/lib/stellarbroker.js.map +1 -1
- package/package.json +1 -1
- package/src/client.js +30 -33
- package/src/estimate.js +4 -3
- package/src/index.d.ts +65 -28
- package/src/index.js +2 -2
- package/src/quote-request.js +3 -3
- package/src/quote-result.js +93 -0
- package/src/tx-processor.js +7 -3
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ notifications from the server without delays. Trading, retries, and results conf
|
|
|
16
16
|
background.
|
|
17
17
|
|
|
18
18
|
```js
|
|
19
|
-
import StellarBrokerClient from '@stellar-broker/client'
|
|
19
|
+
import {StellarBrokerClient} from '@stellar-broker/client'
|
|
20
20
|
|
|
21
21
|
//create client instance
|
|
22
22
|
const client = new StellarBrokerClient({partnerKey: '<your_partner_key>'})
|
|
@@ -73,7 +73,7 @@ client.connect() //only once
|
|
|
73
73
|
//request a price quote
|
|
74
74
|
client.quote({
|
|
75
75
|
sellingAsset: 'xlm',
|
|
76
|
-
buyingAsset: '
|
|
76
|
+
buyingAsset: 'USDC-GDK2GNB4Q6FKNW2GNJIQFARI4RMSHV5DN5G4BBXX2F24RT5I4QT7TWZ7',
|
|
77
77
|
sellingAmount: '1000', //1000.0000000 XLM
|
|
78
78
|
slippageTolerance: 0.02 //2%
|
|
79
79
|
})
|
|
@@ -108,7 +108,7 @@ import {estimateSwap} from '@stellar-broker/client'
|
|
|
108
108
|
|
|
109
109
|
estimateSwap({
|
|
110
110
|
sellingAsset: 'xlm',
|
|
111
|
-
buyingAsset: '
|
|
111
|
+
buyingAsset: 'USDC-GDK2GNB4Q6FKNW2GNJIQFARI4RMSHV5DN5G4BBXX2F24RT5I4QT7TWZ7',
|
|
112
112
|
sellingAmount: '1000',
|
|
113
113
|
slippageTolerance: 0.02 //2%
|
|
114
114
|
})
|
package/lib/stellarbroker.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(
|
|
1
|
+
!function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r(require("@stellar/stellar-sdk")):"function"==typeof define&&define.amd?define(["@stellar/stellar-sdk"],r):"object"==typeof exports?exports.stellarbroker=r(require("@stellar/stellar-sdk")):e.stellarbroker=r(e["@stellar/stellar-sdk"])}(this,(e=>(()=>{"use strict";var r={346:r=>{r.exports=e}},t={},s={};return function e(s){var o=t[s];if(void 0!==o)return o.exports;var l=t[s]={exports:{}};return r[s](l,l.exports,e),l.exports}(346),Error,new Set(["quote","paused","progress","finished","error"]),s.default})()));
|
|
2
2
|
//# sourceMappingURL=stellarbroker.js.map
|
package/lib/stellarbroker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stellarbroker.js","mappings":"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","sources":["webpack://stellarbroker/webpack/universalModuleDefinition","webpack://stellarbroker/external umd \"@stellar/stellar-sdk\"","webpack://stellarbroker/webpack/bootstrap","webpack://stellarbroker/webpack/runtime/define property getters","webpack://stellarbroker/webpack/runtime/hasOwnProperty shorthand","webpack://stellarbroker/./src/errors.js","webpack://stellarbroker/./src/events.js","webpack://stellarbroker/./src/asset.js","webpack://stellarbroker/./src/quote-request.js","webpack://stellarbroker/./src/tx-processor.js","webpack://stellarbroker/./src/authorization.js","webpack://stellarbroker/./src/client.js","webpack://stellarbroker/./src/cjs.js","webpack://stellarbroker/./src/estimate.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"@stellar/stellar-sdk\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"@stellar/stellar-sdk\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"stellarbroker\"] = factory(require(\"@stellar/stellar-sdk\"));\n\telse\n\t\troot[\"stellarbroker\"] = factory(root[\"@stellar/stellar-sdk\"]);\n})(this, (__WEBPACK_EXTERNAL_MODULE__346__) => {\nreturn ","module.exports = __WEBPACK_EXTERNAL_MODULE__346__;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","export class StellarBrokerError extends Error {\n constructor(code, message) {\n super(message)\n this.code = code\n }\n\n /**\n * Numeric error code\n * @type {number}\n * @readonly\n */\n code = 0\n}\n\nconst errors = {\n invalidInitParam(param) {\n return new StellarBrokerError(1, `Invalid parameter value: \"${param}\"`)\n },\n invalidAuthorizationParam() {\n return new StellarBrokerError(2, 'Invalid authorization secret key or callback provided')\n },\n notConnected() {\n return new StellarBrokerError(3, 'Client not connected to the server')\n },\n quoteNotSet() {\n return new StellarBrokerError(11, 'Price quote not available')\n },\n quoteExpired() {\n return new StellarBrokerError(12, 'Price quote expired')\n },\n quoteError(message) {\n return new StellarBrokerError(13, 'Price quotation error: ' + message)\n },\n invalidQuoteParam(invalidParamName = 'asset', details) {\n return new StellarBrokerError(14, `Invalid quote request parameter: \"${invalidParamName}\". ${details}`)\n },\n tradeInProgress() {\n return new StellarBrokerError(20, 'Cannot change quote while trade is in progress')\n },\n invalidSwapTx() {\n return new StellarBrokerError(21, 'Invalid swap transaction received from the server')\n },\n failedToSignTx() {\n return new StellarBrokerError(22, 'Failed to sign received transaction')\n },\n unsupportedEventType(type) {\n return new StellarBrokerError(31, 'Unknown event type: ' + type)\n },\n\n\n serverError(message) {\n return new StellarBrokerError(101, message)\n }\n}\n\nexport default errors","/**\r\n * @param {string} type\r\n * @param {{}} data\r\n * @param {string} [key]\r\n * @return {CustomEvent}\r\n */\r\nexport function buildEvent(type, data, key) {\r\n const evt = new CustomEvent(type, {detail: data})\r\n evt[key || type] = data\r\n return evt\r\n}","import {Asset, StrKey} from '@stellar/stellar-sdk'\nimport errors from './errors.js'\n\n/**\n * @param {string|Asset|{}} asset\n * @return {Asset}\n */\nexport function convertToStellarAsset(asset) {\n if (asset instanceof Asset)\n return asset\n if (asset === 'xlm' || asset === 'XLM' || asset.asset_type === 'native')\n return Asset.native()\n if (asset.asset_type)\n return new Asset(asset.asset_code, asset.asset_issuer)\n const [code, issuer] = asset.includes('-') ?\n asset.split('-') :\n asset.split(':')\n return new Asset(code, issuer)\n}\n\nexport function parseAsset(asset, parameter) {\n if (typeof asset === 'string') {\n if (asset === 'XLM' || asset === 'xlm' || asset === 'native')\n return 'XLM'\n if (asset.includes(':')) {\n const [code, issuer] = asset.split(':')\n validateCode(code)\n validateAccount(issuer, parameter)\n return code + '-' + issuer\n }\n if (asset.includes('-')) {\n const [code, issuer] = asset.split('-')\n validateCode(code)\n validateAccount(issuer, parameter)\n return asset\n }\n }\n throw errors.invalidQuoteParam(parameter, 'Invalid asset')\n}\n\nfunction validateCode(code, parameter) {\n if (!/^[a-zA-Z0-9]{1,12}$/.test(code))\n throw errors.invalidQuoteParam(parameter, 'Invalid asset code: ' + (!code ? 'missing' : code))\n return code\n}\n\nfunction validateAccount(account, param) {\n if (!account || !StrKey.isValidEd25519PublicKey(account))\n throw errors.invalidQuoteParam(param, 'Invalid account address: ' + (!account ? 'missing' : account))\n return account\n}\n","import errors from './errors.js'\nimport {parseAsset} from './asset.js'\n\n/**\n * @typedef {object} SwapQuoteParams\n * @property {string} sellingAsset - Asset to sell\n * @property {string} buyingAsset - Asset to buy\n * @property {string} [sellingAmount] - Amount of selling asset\n * @property {number} [slippageTolerance] - Swap slippage tolerance (0.02 by default - 2%)\n */\n\n/**\n * @param {SwapQuoteParams} params\n * @return {SwapQuoteParams}\n */\nexport function validateQuoteRequest(params) {\n const {\n sellingAsset, selling_asset, buyingAsset, buying_asset, sellingAmount, selling_amount,\n buyingAmount, buying_amount, slippageTolerance, slippage_tolerance, ...other\n } = params\n const res = {\n sellingAsset: parseAsset(sellingAsset || selling_asset, 'sellingAsset'),\n buyingAsset: parseAsset(buyingAsset || buying_asset, 'buyingAsset'),\n sellingAmount: parseAmount(sellingAmount || selling_amount, 'sellingAmount'),\n //buyingAmount: parseAmount(buyingAmount || buying_amount, 'buyingAmount'),\n slippageTolerance: parseSlippageTolerance(slippageTolerance || slippage_tolerance || 0.02, 'slippageTolerance')\n }\n if (res.buyingAsset === res.sellingAsset)\n throw errors.invalidQuoteParam('buyingAsset', 'Buying asset can\\'t be the same as selling asset')\n if (res.sellingAmount === undefined)\n throw errors.invalidQuoteParam('sellingAmount', 'Parameter \"sellingAmount\" parameter is required')\n /*if (res.buyingAmount !== undefined && res.sellingAmount !== undefined)\n throw errors.invalidQuoteParam('sellingAmount', 'Parameters \"buyingAmount\" and \"sellingAmount\" are mutually exclusive')*/\n Object.assign(res, other) //add remaining optional params\n Object.freeze(res)\n return res\n}\n\nfunction parseAmount(amount, parameter) {\n if (amount === undefined)\n return undefined\n const parsed = parseFloat(amount)\n if (isNaN(parsed) || parsed <= 0)\n throw errors.invalidQuoteParam(parameter, 'Invalid asset amount: ' + amount)\n return amount\n}\n\nfunction parseSlippageTolerance(src, parameter) {\n const tolerance = parseFloat(src)\n if (isNaN(tolerance))\n throw errors.invalidQuoteParam(parameter, 'Invalid slippage tolerance, number expected')\n if (tolerance < 0)\n throw errors.invalidQuoteParam(parameter, 'Slippage tolerance is too small, expected value >= 0')\n if (tolerance > 0.5)\n throw errors.invalidQuoteParam(parameter, 'Slippage tolerance is too large, expected value < 0.5 (50%)')\n return tolerance\n}","import {hash, Keypair, nativeToScVal, StrKey, TransactionBuilder, xdr} from '@stellar/stellar-sdk'\nimport errors from './errors.js'\n\n/**\n * @param {StellarBrokerClient} client\n * @param {{xdr: string, hash: string, networkFee: string, [confirmed]: boolean}} txRequest\n * @return {Promise<string>}\n */\nexport async function processTxRequest(client, txRequest) {\n //parse incoming transaction\n let tx\n try {\n tx = TransactionBuilder.fromXDR(txRequest.xdr, client.network)\n } catch (e) {\n throw errors.invalidSwapTx()\n }\n //check that transaction is correct\n if (!validateTransaction(client, tx))\n throw errors.invalidSwapTx()\n //if transaction has not been authorized yet by the channel account\n const isSorobanTx = tx.operations[0].auth?.length > 0\n if (isSorobanTx) {\n //send tx back to the server\n if (!tx.signatures.length) {\n //sign auth\n await authorizeInvocation(client, tx)\n tx = await signTx(client, tx)\n return tx.toXDR()//wait for the signed tx from the server to wrap it with fee bump tx\n }\n } else {\n //sign transaction\n tx = await signTx(client, tx)\n }\n //wrap with fee bump\n let wrapped = TransactionBuilder.buildFeeBumpTransaction(client.trader, txRequest.networkFee, tx, client.network)\n //sign fee bump wrapper tx\n wrapped = await signTx(client, wrapped)\n //respond with signed transaction\n return wrapped.toXDR()\n}\n\n/**\n * @param {StellarBrokerClient} client\n * @param {TransactionI} tx\n * @return {Promise<TransactionI>}\n * @private\n */\nasync function authorizeInvocation(client, tx) {\n //from https://github.com/stellar/js-stellar-base/blob/e3d6fc3351e7d242b374c7c6057668366364a279/src/auth.js#L97\n const auth = tx.operations[0].auth[0]\n /** @type {xdr.SorobanAddressCredentials} */\n const addrAuth = auth.credentials().address()\n addrAuth.signatureExpirationLedger(tx.ledgerBounds.maxLedger + 1)\n\n const networkId = hash(Buffer.from(tx.networkPassphrase))\n const preimage = xdr.HashIdPreimage.envelopeTypeSorobanAuthorization(\n new xdr.HashIdPreimageSorobanAuthorization({\n networkId,\n nonce: addrAuth.nonce(),\n invocation: auth.rootInvocation(),\n signatureExpirationLedger: addrAuth.signatureExpirationLedger()\n })\n )\n const payload = hash(preimage.toXDR())\n const signature = await client.authorization.authorize(payload)\n const publicKey = StrKey.encodeEd25519PublicKey(addrAuth.address().accountId().value())\n const sigScVal = nativeToScVal(\n {\n public_key: StrKey.decodeEd25519PublicKey(publicKey),\n signature\n },\n {\n type: {\n public_key: ['symbol', null],\n signature: ['symbol', null]\n }\n }\n )\n\n addrAuth.signature(xdr.ScVal.scvVec([sigScVal]))\n}\n\n/**\n * @param {StellarBrokerClient} client\n * @param {TransactionI} tx\n * @return {Promise<TransactionI>}\n * @private\n */\nfunction signTx(client, tx) {\n return client.authorization.authorize(tx)\n .then(tx => {\n if (typeof tx === 'string') { //normalize response\n tx = TransactionBuilder.fromXDR(tx, client.network)\n }\n if (!tx || tx.signatures?.length < 1)\n throw new Error(`Transaction was not signed`)\n return tx\n })\n .catch(e => {\n console.error(e)\n throw errors.failedToSignTx()\n })\n}\n\n/**\n * @param {StellarBrokerClient} client\n * @param {Transaction} tx\n * @throws {StellarBrokerError} Invalid swap transaction received\n */\nfunction validateTransaction(client, tx) {\n /*if (!(tx instanceof FeeBumpTransaction))\n return false\n const {innerTransaction} = tx\n if (tx.feeSource !== this.source)\n return false*/\n for (let swap of tx.operations) {\n if (swap.type === 'invokeHostFunction')\n continue //TODO: add additional validation\n if (swap.type !== 'pathPaymentStrictSend' && swap.type !== 'pathPaymentStrictReceive')\n return false\n const isFee = swap.destination !== client.trader\n if (isFee) {\n if (swap.type !== 'pathPaymentStrictSend')\n return false\n if ((swap.source && swap.source !== client.trader))\n return false\n } else {\n if ((swap.source && swap.source !== swap.destination) || swap.destination !== client.trader)\n return false\n }\n }\n //TODO: check assets and amounts\n return true\n}","import {Keypair} from '@stellar/stellar-sdk'\nimport errors from './errors.js'\n\nexport class AuthorizationWrapper {\n /**\n * @param {ClientAuthorizationParams} authorization\n */\n constructor(authorization) {\n if (typeof authorization === 'string') {\n try {\n this.authorization = Keypair.fromSecret(authorization)\n return\n } catch (e) {\n throw errors.invalidAuthorizationParam()\n }\n } else if (typeof authorization === 'function') {\n this.authorization = authorization\n return\n }\n throw errors.invalidAuthorizationParam()\n }\n\n /**\n * @type {Keypair|ClientAuthorizationCallback}\n * @private\n */\n authorization\n\n /**\n * Authorize transaction or invocation footprint hash\n * @param {TransactionI|Buffer} payload\n * @return {Promise<TransactionI|Buffer>}\n */\n async authorize(payload) {\n if (this.authorization instanceof Keypair) {\n if (payload.sign){\n payload.sign(this.authorization)\n return payload\n }\n return this.authorization.sign(payload)\n }\n return await promisify(this.authorization(payload))\n }\n}\n\n/**\n * @param {*|Promise} callResult\n * @return {Promise}\n */\nfunction promisify(callResult) {\n if (!(callResult instanceof Promise)) {\n if (!callResult)\n return Promise.reject()\n callResult = Promise.resolve(callResult)\n }\n return callResult\n}\n\n/**\n * @typedef {function(TransactionI|Buffer):Promise<TransactionI|Buffer>} ClientAuthorizationCallback - Async authorization callback\n */\n\n/**\n * @typedef {string|ClientAuthorizationCallback} ClientAuthorizationParams - Authorization method, either account secret key or an authorization callback\n */","import {Networks, StrKey} from '@stellar/stellar-sdk'\nimport errors from './errors.js'\nimport {buildEvent} from './events.js'\nimport {validateQuoteRequest} from './quote-request.js'\nimport {processTxRequest} from './tx-processor.js'\nimport {AuthorizationWrapper} from './authorization.js'\n\nexport default class StellarBrokerClient {\n /**\n * @param {ClientInitializationParams} params\n */\n constructor(params) {\n this.partnerKey = params.partnerKey\n this.emitter = new EventTarget()\n this.network = Networks.PUBLIC\n if (!params.account || !StrKey.isValidEd25519PublicKey(params.account))\n throw errors.invalidQuoteParam('account', 'Invalid trader account address: ' + (!params.account ? 'missing' : params.account))\n this.trader = params.account\n this.authorization = new AuthorizationWrapper(params.authorization)\n }\n\n /**\n * @type {string}\n * @private\n */\n uid\n /**\n * @type {ClientStatus}\n * @readonly\n */\n status = 'disconnected'\n /**\n * @type {WebSocket}\n * @private\n */\n socket\n /**\n * @type {EventTarget}\n * @private\n */\n emitter\n /**\n * @type {string}\n * @private\n */\n origin = 'https://api.stellar.broker'\n /**\n * Stellar network passphrase\n * @type {string}\n * @readonly\n */\n network = ''\n /**\n * Last quote request submitted by the client\n * @type {SwapQuoteParams}\n * @readonly\n */\n quoteRequest\n /**\n * Last quote received from the sever\n * @type {SwapQuoteResult}\n * @readonly\n */\n lastQuote\n /**\n * Current quote accepted for the trading\n * @private\n */\n tradeQuote\n /**\n * API key of the partner\n * @type {string}\n * @readonly\n */\n partnerKey\n /**\n * Account secret key or authorization callback\n * @type {AuthorizationWrapper}\n * @private\n */\n authorization\n /**\n * Trader account public key\n * @type {string}\n * @readonly\n */\n trader\n\n /**\n * Connect to the StellarBroker server\n * @return {Promise<StellarBrokerClient>}\n */\n connect() {\n if (this.socket?.readyState === WebSocket.OPEN)\n return Promise.resolve(this) //already opened\n this.socket = new WebSocket(this.origin + '/ws?partner=' + encodeURIComponent(this.partnerKey))\n this.socket.onmessage = this.processMessage.bind(this)\n this.socket.onclose = () => {\n if (this.status !== 'disconnected') {\n this.status = 'disconnected'\n this.notifyError(errors.notConnected())\n }\n console.log('Connection closed')\n }\n\n this.socket.onerror = e => console.error(e)\n\n return new Promise((confirm, reject) => { //TODO: use 'once'\n const expirationTimeout = setTimeout(() => reject(this), 2000) // 2s timeout\n this.onSocketOpen = () => {\n this.status = 'ready'\n this.heartbeat()\n this.onSocketOpen = undefined\n clearTimeout(expirationTimeout)\n confirm(this)\n }\n })\n }\n\n /**\n * Process incoming message\n * @param message\n * @private\n */\n processMessage(message) {\n const raw = JSON.parse(message.data)\n switch (raw.type) {\n case 'connected':\n this.uid = raw.uid\n if (this.onSocketOpen) {\n this.onSocketOpen()\n }\n if (this.status === 'disconnected') {\n this.status = 'ready'\n }\n break\n case 'quote':\n this.lastQuote = raw.quote\n this.lastQuote.ts = new Date()\n //send event to the client app\n this.emitter.dispatchEvent(buildEvent('quote', this.lastQuote))\n break\n case 'paused':\n //quotation paused due to inactivity\n this.emitter.dispatchEvent(buildEvent('paused', {}))\n break\n case 'tx':\n if (this.status !== 'trade') {\n console.log('Received tx in non-trading state', this.status, raw)\n return //skip unless trading is in progress\n }\n processTxRequest(this, raw)\n .then(xdr => {\n this.send({\n type: 'tx',\n hash: raw.hash,\n xdr\n })\n })\n .catch(e => this.notifyError(e))\n break\n case 'stop':\n this.emitter.dispatchEvent(buildEvent('finished', {\n status: raw.status,\n sold: raw.sold,\n bought: raw.bought\n }, 'result'))\n this.status = 'ready'\n this.tradeQuote = undefined\n break\n case 'progress':\n this.emitter.dispatchEvent(buildEvent('progress', {\n sold: raw.sold,\n bought: raw.bought\n }, 'status'))\n break\n case 'ping':\n if (raw.uid === this.uid) {\n this.heartbeat()\n this.send({type: 'pong', uid: this.uid})\n }\n break\n case 'error':\n this.stop()\n this.notifyError(raw.error)\n break\n default:\n console.log('Unknown message type: ' + raw.type)\n break\n }\n }\n\n /**\n * Request swap quote\n * @param {SwapQuoteParams} params - Quote parameters\n */\n quote(params) {\n if (this.status === 'trade')\n throw errors.tradeInProgress()\n this.quoteRequest = validateQuoteRequest(params)\n this.status = 'quote'\n this.connect()\n .then(() => {\n this.status = 'quote'\n this.send({\n type: 'quote',\n ...this.quoteRequest\n })\n })\n }\n\n /**\n * Confirm current quote and start trading\n */\n confirmQuote() {\n if (this.status === 'disconnected')\n throw errors.notConnected()\n if (this.status === 'trade')\n throw errors.tradeInProgress()\n if (this.status !== 'quote' || !this.lastQuote)\n throw errors.quoteNotSet()\n if ((new Date() - this.lastQuote.ts) > 10_000) //do not allow stale quotes quoted more than 10s ago\n throw errors.quoteExpired()\n if (this.lastQuote.status !== 'success')\n throw errors.quoteError(this.lastQuote.error || 'quote not available')\n\n this.tradeQuote = this.lastQuote\n this.send({\n type: 'trade',\n account: this.trader\n })\n this.status = 'trade'\n }\n\n /**\n * Stop quotation/trading\n */\n stop() {\n if (this.status !== 'trade' && this.status !== 'quote')\n return\n this.send({type: 'stop'})\n this.tradeQuote = undefined\n this.status = 'ready'\n }\n\n /**\n * @param {{}} data\n * @private\n */\n send(data) {\n this.socket.send(JSON.stringify(data))\n }\n\n /**\n * @private\n */\n heartbeat() {\n clearTimeout(this.pingHandler)\n this.pingHandler = setTimeout(() => {\n console.warn('Lost connection with the server')\n this.socket.close()\n }, 7_000) // 7 seconds heartbeat timeout\n }\n\n /**\n * Add event listener\n * @param {StellarBrokerClientEvent} type\n * @param {function} callback\n */\n on(type, callback) {\n validateEventType(type)\n this.emitter.addEventListener(type, callback)\n }\n\n /**\n * Add event listener that will be executed once\n * @param {StellarBrokerClientEvent} type\n * @param {function} callback\n */\n once(type, callback) {\n validateEventType(type)\n this.emitter.addEventListener(type, callback, {once: true})\n }\n\n /**\n * Remove event listener\n * @param {StellarBrokerClientEvent} type\n * @param {function} callback\n */\n off(type, callback) {\n validateEventType(type)\n this.emitter.removeEventListener(type, callback)\n }\n\n /**\n * Close underlying connection and finalize the client\n */\n close() {\n try {\n //TODO: remove all attached event listeners\n this.status = 'disconnected'\n this.socket.close()\n } catch (e) {\n }\n }\n\n /**\n * @param {Error} e\n * @private\n */\n notifyError(e) {\n console.error(e)\n try {\n this.emitter.dispatchEvent(buildEvent('error', e instanceof Error ? e.message : e))\n } catch (e) {\n console.error(e)\n }\n }\n}\n\nfunction validateEventType(type) {\n if (!StellarBrokerEvents.includes(type))\n throw errors.unsupportedEventType(type)\n}\n\nexport const StellarBrokerEvents = ['quote', 'paused', 'progress', 'finished', 'error']\n\n/**\n * @typedef {object} ClientInitializationParams\n * @property {string} account - Trader account address\n * @property {ClientAuthorizationParams} authorization - Authorization method, either account secret key or an authorization callback\n * @property {string} [partnerKey] - Partner key\n */\n\n/**\n * @typedef {'disconnected'|'ready'|'quote'|'trade'} ClientStatus\n */\n\n/**\n * @typedef {'quote'|'paused'|'progress'|'finished'|'error'} StellarBrokerClientEvent\n */\n\n/**\n * @typedef {object} SwapQuoteResult\n * @property {string} ts - Quote timestamp formatted as ISO date\n * @property {string} sellingAsset - Asset to sell\n * @property {string} buyingAsset - Asset to buy\n * @property {number} slippageTolerance - Swap slippage tolerance\n * @property {string} sellingAmount - Amount of the selling asset\n * @property {string} [estimatedBuyingAmount] - Estimated amount of buyingAsset to receive\n * @property {{selling: string, buying: string, path: string[]}} [directTrade] - Equivalent direct path_payment trade estimate\n * @property {string} [error] - Error details from the server (for failed quotes)\n */\n","import StellarBrokerClient from './client.js'\r\nimport {estimateSwap} from './estimate.js'\r\n\r\nStellarBrokerClient.estimateSwap = estimateSwap\r\n\r\nexport default StellarBrokerClient","import errors, {StellarBrokerError} from './errors.js'\r\nimport {validateQuoteRequest} from './quote-request.js'\r\n\r\n/**\r\n * Request single swap quote estimate without trading\r\n * @param {SwapQuoteParams} params\r\n * @return {Promise<SwapQuoteResult>}\r\n */\r\nexport async function estimateSwap(params) {\r\n const query = Object.entries(validateQuoteRequest(params))\r\n .filter(kv => kv[1] !== undefined)\r\n .map(([param, value]) => encodeURIComponent(param) + '=' + encodeURIComponent(value))\r\n const url = (params.origin || 'https://api.stellar.broker') + '/quote?' + query.join('&')\r\n try {\r\n const res = await fetch(url).then(r => r.json())\r\n if (res.status !== 'success')\r\n throw errors.quoteError(res.error || 'Quote not available')\r\n return res\r\n } catch (e) {\r\n if (e instanceof StellarBrokerError)\r\n throw e\r\n throw errors.quoteError('Failed to fetch quote')\r\n return null\r\n }\r\n}"],"names":["root","factory","exports","module","require","define","amd","this","__WEBPACK_EXTERNAL_MODULE__346__","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","d","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","StellarBrokerError","Error","constructor","code","message","super","invalidInitParam","param","invalidAuthorizationParam","notConnected","quoteNotSet","quoteExpired","quoteError","invalidQuoteParam","invalidParamName","details","tradeInProgress","invalidSwapTx","failedToSignTx","unsupportedEventType","type","serverError","buildEvent","data","evt","CustomEvent","detail","parseAsset","asset","parameter","includes","issuer","split","validateCode","validateAccount","errors","test","account","StrKey","isValidEd25519PublicKey","validateQuoteRequest","params","sellingAsset","selling_asset","buyingAsset","buying_asset","sellingAmount","selling_amount","buyingAmount","buying_amount","slippageTolerance","slippage_tolerance","other","res","parseAmount","parseSlippageTolerance","assign","freeze","amount","parsed","parseFloat","isNaN","src","tolerance","signTx","client","tx","authorization","authorize","then","TransactionBuilder","fromXDR","network","signatures","length","catch","e","console","error","AuthorizationWrapper","Keypair","fromSecret","payload","sign","callResult","Promise","reject","resolve","promisify","StellarBrokerClient","partnerKey","emitter","EventTarget","Networks","PUBLIC","trader","uid","status","socket","origin","quoteRequest","lastQuote","tradeQuote","connect","readyState","WebSocket","OPEN","encodeURIComponent","onmessage","processMessage","bind","onclose","notifyError","log","onerror","confirm","expirationTimeout","setTimeout","onSocketOpen","heartbeat","clearTimeout","raw","JSON","parse","quote","ts","Date","dispatchEvent","async","txRequest","xdr","swap","operations","destination","source","validateTransaction","auth","addrAuth","credentials","address","signatureExpirationLedger","ledgerBounds","maxLedger","networkId","hash","Buffer","from","networkPassphrase","preimage","HashIdPreimage","envelopeTypeSorobanAuthorization","HashIdPreimageSorobanAuthorization","nonce","invocation","rootInvocation","toXDR","signature","publicKey","encodeEd25519PublicKey","accountId","value","sigScVal","nativeToScVal","public_key","decodeEd25519PublicKey","ScVal","scvVec","authorizeInvocation","wrapped","buildFeeBumpTransaction","networkFee","processTxRequest","send","sold","bought","stop","confirmQuote","stringify","pingHandler","warn","close","on","callback","validateEventType","addEventListener","once","off","removeEventListener","StellarBrokerEvents","estimateSwap","query","entries","filter","kv","map","url","join","fetch","r","json"],"sourceRoot":""}
|
|
1
|
+
{"version":3,"file":"stellarbroker.js","mappings":"CAAA,SAA2CA,EAAMC,GAC1B,iBAAZC,SAA0C,iBAAXC,OACxCA,OAAOD,QAAUD,EAAQG,QAAQ,yBACR,mBAAXC,QAAyBA,OAAOC,IAC9CD,OAAO,CAAC,wBAAyBJ,GACP,iBAAZC,QACdA,QAAuB,cAAID,EAAQG,QAAQ,yBAE3CJ,EAAoB,cAAIC,EAAQD,EAAK,wBACtC,CATD,CASGO,MAAOC,G,kCCTVL,EAAOD,QAAUM,C,GCCbC,EAA2B,CAAC,E,YAGhC,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBE,IAAjBD,EACH,OAAOA,EAAaV,QAGrB,IAAIC,EAASM,EAAyBE,GAAY,CAGjDT,QAAS,CAAC,GAOX,OAHAY,EAAoBH,GAAUR,EAAQA,EAAOD,QAASQ,GAG/CP,EAAOD,OACf,C,MCtBwCa,MCyUZ,IAAIC,IAAI,CAAC,QAAS,SAAU,WAAY,WAAY,U","sources":["webpack://stellarbroker/webpack/universalModuleDefinition","webpack://stellarbroker/external umd \"@stellar/stellar-sdk\"","webpack://stellarbroker/webpack/bootstrap","webpack://stellarbroker/./src/errors.js","webpack://stellarbroker/./src/client.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"@stellar/stellar-sdk\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"@stellar/stellar-sdk\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"stellarbroker\"] = factory(require(\"@stellar/stellar-sdk\"));\n\telse\n\t\troot[\"stellarbroker\"] = factory(root[\"@stellar/stellar-sdk\"]);\n})(this, (__WEBPACK_EXTERNAL_MODULE__346__) => {\nreturn ","module.exports = __WEBPACK_EXTERNAL_MODULE__346__;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","export class StellarBrokerError extends Error {\n constructor(code, message) {\n super(message)\n this.code = code\n }\n\n /**\n * Numeric error code\n * @type {number}\n * @readonly\n */\n code = 0\n}\n\nconst errors = {\n invalidInitParam(param) {\n return new StellarBrokerError(1, `Invalid parameter value: \"${param}\"`)\n },\n invalidAuthorizationParam() {\n return new StellarBrokerError(2, 'Invalid authorization secret key or callback provided')\n },\n notConnected() {\n return new StellarBrokerError(3, 'Client not connected to the server')\n },\n quoteNotSet() {\n return new StellarBrokerError(11, 'Price quote not available')\n },\n quoteExpired() {\n return new StellarBrokerError(12, 'Price quote expired')\n },\n quoteError(message) {\n return new StellarBrokerError(13, 'Price quotation error: ' + message)\n },\n invalidQuoteParam(invalidParamName = 'asset', details) {\n return new StellarBrokerError(14, `Invalid quote request parameter: \"${invalidParamName}\". ${details}`)\n },\n tradeInProgress() {\n return new StellarBrokerError(20, 'Cannot change quote while trade is in progress')\n },\n invalidSwapTx() {\n return new StellarBrokerError(21, 'Invalid swap transaction received from the server')\n },\n failedToSignTx() {\n return new StellarBrokerError(22, 'Failed to sign received transaction')\n },\n unsupportedEventType(type) {\n return new StellarBrokerError(31, 'Unknown event type: ' + type)\n },\n\n\n serverError(message) {\n return new StellarBrokerError(101, message)\n }\n}\n\nexport default errors","import {Networks, StrKey} from '@stellar/stellar-sdk'\nimport errors from './errors.js'\nimport {buildEvent} from './events.js'\nimport {processTxRequest} from './tx-processor.js'\nimport {validateQuoteRequest} from './quote-request.js'\nimport {QuoteResult} from './quote-result.js'\nimport {AuthorizationWrapper} from './authorization.js'\n\n/**\n * Client for StellarBroker service\n */\nexport class StellarBrokerClient {\n /**\n * @param {ClientInitializationParams} params\n */\n constructor(params) {\n this.partnerKey = params.partnerKey\n this.emitter = new EventTarget()\n this.network = Networks.PUBLIC\n this.trader = params.account\n this.authorization = new AuthorizationWrapper(params.authorization)\n }\n\n /**\n * @type {string}\n * @private\n */\n uid\n /**\n * @type {ClientSessionStatus}\n * @readonly\n */\n status = 'disconnected'\n /**\n * @type {WebSocket}\n * @private\n */\n socket\n /**\n * @type {EventTarget}\n * @private\n */\n emitter\n /**\n * @type {string}\n * @private\n */\n origin = 'https://api.stellar.broker'\n /**\n * Stellar network passphrase\n * @type {string}\n * @readonly\n */\n network = ''\n /**\n * Last quote request submitted by the client\n * @type {QuoteParams}\n * @readonly\n */\n quoteRequest\n /**\n * Last quote received from the sever\n * @type {QuoteResult}\n * @readonly\n */\n lastQuote\n /**\n * Current quote accepted for the trading\n * @private\n */\n tradeQuote\n /**\n * API key of the partner\n * @type {string}\n * @readonly\n */\n partnerKey\n /**\n * Account secret key or authorization callback\n * @type {AuthorizationWrapper}\n * @private\n */\n authorization\n /**\n * Trader account public key\n * @type {string}\n * @readonly\n */\n trader\n\n /**\n * Connect to the StellarBroker server\n * @return {Promise<StellarBrokerClient>}\n */\n connect() {\n if (this.socket?.readyState === WebSocket.OPEN)\n return Promise.resolve(this) //already opened\n this.socket = new WebSocket(this.origin + '/ws?partner=' + encodeURIComponent(this.partnerKey))\n this.socket.onmessage = this.processMessage.bind(this)\n this.socket.onclose = () => {\n if (this.status !== 'disconnected') {\n this.status = 'disconnected'\n this.notifyError(errors.notConnected())\n }\n console.log('Connection closed')\n }\n\n this.socket.onerror = e => console.error(e)\n\n return new Promise((confirm, reject) => { //TODO: use 'once'\n const expirationTimeout = setTimeout(() => reject(this), 2000) // 2s timeout\n this.onSocketOpen = () => {\n this.status = 'ready'\n this.heartbeat()\n this.onSocketOpen = undefined\n clearTimeout(expirationTimeout)\n confirm(this)\n }\n })\n }\n\n /**\n * Process incoming message\n * @param message\n * @private\n */\n processMessage(message) {\n const raw = JSON.parse(message.data)\n switch (raw.type) {\n case 'connected':\n this.uid = raw.uid\n if (this.onSocketOpen) {\n this.onSocketOpen()\n }\n if (this.status === 'disconnected') {\n this.status = 'ready'\n }\n break\n case 'quote':\n this.lastQuote = new QuoteResult(raw.quote)\n //send event to the client app\n this.emitter.dispatchEvent(buildEvent('quote', this.lastQuote))\n break\n case 'paused':\n //quotation paused due to inactivity\n this.emitter.dispatchEvent(buildEvent('paused', {}))\n break\n case 'tx':\n if (this.status !== 'trade') {\n console.log('Received tx in a non-trading state', this.status, raw)\n return //skip unless trading is in progress\n }\n processTxRequest(this, raw)\n .then(xdr => {\n this.send({\n type: 'tx',\n hash: raw.hash,\n xdr\n })\n })\n .catch(e => this.notifyError(e))\n break\n case 'stop':\n this.emitter.dispatchEvent(buildEvent('finished', {\n status: raw.status,\n sold: raw.sold,\n bought: raw.bought\n }, 'result'))\n this.status = 'ready'\n this.tradeQuote = undefined\n break\n case 'progress':\n this.emitter.dispatchEvent(buildEvent('progress', {\n sold: raw.sold,\n bought: raw.bought\n }, 'status'))\n break\n case 'ping':\n if (raw.uid === this.uid) {\n this.heartbeat()\n this.send({type: 'pong', uid: this.uid})\n }\n break\n case 'error':\n this.stop()\n this.notifyError(raw.error)\n break\n default:\n console.log('Unknown message type: ' + raw.type)\n break\n }\n }\n\n /**\n * Request swap quote\n * @param {QuoteParams} params - Quote parameters\n */\n quote(params) {\n if (this.status === 'trade')\n throw errors.tradeInProgress()\n this.quoteRequest = validateQuoteRequest(params)\n\n this.status = 'quote'\n this.connect()\n .then(() => {\n this.status = 'quote'\n this.send({\n type: 'quote',\n ...this.quoteRequest\n })\n })\n }\n\n /**\n * Confirm current quote and start trading\n * @param {string} [account] - Trader account address (overrides value provided in the constructor)\n */\n confirmQuote(account) {\n if (this.status === 'disconnected')\n throw errors.notConnected()\n if (this.status === 'trade')\n throw errors.tradeInProgress()\n if (this.status !== 'quote' || !this.lastQuote)\n throw errors.quoteNotSet()\n if ((new Date() - this.lastQuote.ts) > 10_000) //do not allow stale quotes quoted more than 10s ago\n throw errors.quoteExpired()\n if (this.lastQuote.status !== 'success')\n throw errors.quoteError(this.lastQuote.error || 'quote not available')\n if (account) {\n this.trader = account\n }\n //ensure that a trader account address provided\n const {trader} = this\n if (!trader || !StrKey.isValidEd25519PublicKey(trader))\n throw errors.invalidQuoteParam('account', 'Invalid trader account address: ' + (!trader ? 'missing' : trader))\n this.tradeQuote = this.lastQuote\n this.send({\n type: 'trade',\n account: trader\n })\n this.status = 'trade'\n }\n\n /**\n * Stop quotation/trading\n */\n stop() {\n if (this.status !== 'trade' && this.status !== 'quote')\n return\n this.send({type: 'stop'})\n this.tradeQuote = undefined\n this.status = 'ready'\n }\n\n /**\n * @param {{}} data\n * @private\n */\n send(data) {\n this.socket.send(JSON.stringify(data))\n }\n\n /**\n * @private\n */\n heartbeat() {\n clearTimeout(this.pingHandler)\n this.pingHandler = setTimeout(() => {\n console.warn('Lost connection with the server')\n this.socket.close()\n }, 7_000) // 7 seconds heartbeat timeout\n }\n\n /**\n * Add event listener\n * @param {StellarBrokerClientEvent} type\n * @param {function} callback\n */\n on(type, callback) {\n validateEventType(type)\n this.emitter.addEventListener(type, callback)\n }\n\n /**\n * Add event listener that will be executed once\n * @param {StellarBrokerClientEvent} type\n * @param {function} callback\n */\n once(type, callback) {\n validateEventType(type)\n this.emitter.addEventListener(type, callback, {once: true})\n }\n\n /**\n * Remove event listener\n * @param {StellarBrokerClientEvent} type\n * @param {function} callback\n */\n off(type, callback) {\n validateEventType(type)\n this.emitter.removeEventListener(type, callback)\n }\n\n /**\n * Close underlying connection and finalize the client\n */\n close() {\n try {\n //TODO: remove all attached event listeners\n this.status = 'disconnected'\n this.socket.close()\n } catch (e) {\n }\n }\n\n /**\n * @param {Error} e\n * @private\n */\n notifyError(e) {\n console.error(e)\n try {\n this.emitter.dispatchEvent(buildEvent('error', e instanceof Error ? e.message : e))\n } catch (e) {\n console.error(e)\n }\n }\n}\n\nconst stellarBrokerEvents = new Set(['quote', 'paused', 'progress', 'finished', 'error'])\n\nfunction validateEventType(type) {\n if (!stellarBrokerEvents.has(type))\n throw errors.unsupportedEventType(type)\n}\n\n/**\n * @typedef {object} ClientInitializationParams\n * @property {ClientAuthorizationParams} authorization - Authorization method, either account secret key or an authorization callback\n * @property {string} [account] - Trader account address\n * @property {string} [partnerKey] - Partner key\n */\n\n/**\n * @typedef {'disconnected'|'ready'|'quote'|'trade'} ClientSessionStatus - Current client session status\n */\n\n/**\n * @typedef {'quote'|'paused'|'progress'|'finished'|'error'} StellarBrokerClientEvent - Event type generated by the client\n */\n"],"names":["root","factory","exports","module","require","define","amd","this","__WEBPACK_EXTERNAL_MODULE__346__","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","Error","Set"],"sourceRoot":""}
|
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import {Networks, StrKey} from '@stellar/stellar-sdk'
|
|
2
2
|
import errors from './errors.js'
|
|
3
3
|
import {buildEvent} from './events.js'
|
|
4
|
-
import {validateQuoteRequest} from './quote-request.js'
|
|
5
4
|
import {processTxRequest} from './tx-processor.js'
|
|
5
|
+
import {validateQuoteRequest} from './quote-request.js'
|
|
6
|
+
import {QuoteResult} from './quote-result.js'
|
|
6
7
|
import {AuthorizationWrapper} from './authorization.js'
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Client for StellarBroker service
|
|
11
|
+
*/
|
|
12
|
+
export class StellarBrokerClient {
|
|
9
13
|
/**
|
|
10
14
|
* @param {ClientInitializationParams} params
|
|
11
15
|
*/
|
|
@@ -13,8 +17,6 @@ export default class StellarBrokerClient {
|
|
|
13
17
|
this.partnerKey = params.partnerKey
|
|
14
18
|
this.emitter = new EventTarget()
|
|
15
19
|
this.network = Networks.PUBLIC
|
|
16
|
-
if (!params.account || !StrKey.isValidEd25519PublicKey(params.account))
|
|
17
|
-
throw errors.invalidQuoteParam('account', 'Invalid trader account address: ' + (!params.account ? 'missing' : params.account))
|
|
18
20
|
this.trader = params.account
|
|
19
21
|
this.authorization = new AuthorizationWrapper(params.authorization)
|
|
20
22
|
}
|
|
@@ -25,7 +27,7 @@ export default class StellarBrokerClient {
|
|
|
25
27
|
*/
|
|
26
28
|
uid
|
|
27
29
|
/**
|
|
28
|
-
* @type {
|
|
30
|
+
* @type {ClientSessionStatus}
|
|
29
31
|
* @readonly
|
|
30
32
|
*/
|
|
31
33
|
status = 'disconnected'
|
|
@@ -52,13 +54,13 @@ export default class StellarBrokerClient {
|
|
|
52
54
|
network = ''
|
|
53
55
|
/**
|
|
54
56
|
* Last quote request submitted by the client
|
|
55
|
-
* @type {
|
|
57
|
+
* @type {QuoteParams}
|
|
56
58
|
* @readonly
|
|
57
59
|
*/
|
|
58
60
|
quoteRequest
|
|
59
61
|
/**
|
|
60
62
|
* Last quote received from the sever
|
|
61
|
-
* @type {
|
|
63
|
+
* @type {QuoteResult}
|
|
62
64
|
* @readonly
|
|
63
65
|
*/
|
|
64
66
|
lastQuote
|
|
@@ -135,10 +137,9 @@ export default class StellarBrokerClient {
|
|
|
135
137
|
}
|
|
136
138
|
break
|
|
137
139
|
case 'quote':
|
|
138
|
-
this.lastQuote = raw.quote
|
|
139
|
-
this.lastQuote.ts = new Date()
|
|
140
|
+
this.lastQuote = new QuoteResult(raw.quote)
|
|
140
141
|
//send event to the client app
|
|
141
|
-
|
|
142
|
+
this.emitter.dispatchEvent(buildEvent('quote', this.lastQuote))
|
|
142
143
|
break
|
|
143
144
|
case 'paused':
|
|
144
145
|
//quotation paused due to inactivity
|
|
@@ -146,7 +147,7 @@ export default class StellarBrokerClient {
|
|
|
146
147
|
break
|
|
147
148
|
case 'tx':
|
|
148
149
|
if (this.status !== 'trade') {
|
|
149
|
-
console.log('Received tx in non-trading state', this.status, raw)
|
|
150
|
+
console.log('Received tx in a non-trading state', this.status, raw)
|
|
150
151
|
return //skip unless trading is in progress
|
|
151
152
|
}
|
|
152
153
|
processTxRequest(this, raw)
|
|
@@ -192,12 +193,13 @@ export default class StellarBrokerClient {
|
|
|
192
193
|
|
|
193
194
|
/**
|
|
194
195
|
* Request swap quote
|
|
195
|
-
* @param {
|
|
196
|
+
* @param {QuoteParams} params - Quote parameters
|
|
196
197
|
*/
|
|
197
198
|
quote(params) {
|
|
198
199
|
if (this.status === 'trade')
|
|
199
200
|
throw errors.tradeInProgress()
|
|
200
201
|
this.quoteRequest = validateQuoteRequest(params)
|
|
202
|
+
|
|
201
203
|
this.status = 'quote'
|
|
202
204
|
this.connect()
|
|
203
205
|
.then(() => {
|
|
@@ -211,8 +213,9 @@ export default class StellarBrokerClient {
|
|
|
211
213
|
|
|
212
214
|
/**
|
|
213
215
|
* Confirm current quote and start trading
|
|
216
|
+
* @param {string} [account] - Trader account address (overrides value provided in the constructor)
|
|
214
217
|
*/
|
|
215
|
-
confirmQuote() {
|
|
218
|
+
confirmQuote(account) {
|
|
216
219
|
if (this.status === 'disconnected')
|
|
217
220
|
throw errors.notConnected()
|
|
218
221
|
if (this.status === 'trade')
|
|
@@ -223,11 +226,17 @@ export default class StellarBrokerClient {
|
|
|
223
226
|
throw errors.quoteExpired()
|
|
224
227
|
if (this.lastQuote.status !== 'success')
|
|
225
228
|
throw errors.quoteError(this.lastQuote.error || 'quote not available')
|
|
226
|
-
|
|
229
|
+
if (account) {
|
|
230
|
+
this.trader = account
|
|
231
|
+
}
|
|
232
|
+
//ensure that a trader account address provided
|
|
233
|
+
const {trader} = this
|
|
234
|
+
if (!trader || !StrKey.isValidEd25519PublicKey(trader))
|
|
235
|
+
throw errors.invalidQuoteParam('account', 'Invalid trader account address: ' + (!trader ? 'missing' : trader))
|
|
227
236
|
this.tradeQuote = this.lastQuote
|
|
228
237
|
this.send({
|
|
229
238
|
type: 'trade',
|
|
230
|
-
account:
|
|
239
|
+
account: trader
|
|
231
240
|
})
|
|
232
241
|
this.status = 'trade'
|
|
233
242
|
}
|
|
@@ -318,36 +327,24 @@ export default class StellarBrokerClient {
|
|
|
318
327
|
}
|
|
319
328
|
}
|
|
320
329
|
|
|
330
|
+
const stellarBrokerEvents = new Set(['quote', 'paused', 'progress', 'finished', 'error'])
|
|
331
|
+
|
|
321
332
|
function validateEventType(type) {
|
|
322
|
-
if (!
|
|
333
|
+
if (!stellarBrokerEvents.has(type))
|
|
323
334
|
throw errors.unsupportedEventType(type)
|
|
324
335
|
}
|
|
325
336
|
|
|
326
|
-
export const StellarBrokerEvents = ['quote', 'paused', 'progress', 'finished', 'error']
|
|
327
|
-
|
|
328
337
|
/**
|
|
329
338
|
* @typedef {object} ClientInitializationParams
|
|
330
|
-
* @property {string} account - Trader account address
|
|
331
339
|
* @property {ClientAuthorizationParams} authorization - Authorization method, either account secret key or an authorization callback
|
|
340
|
+
* @property {string} [account] - Trader account address
|
|
332
341
|
* @property {string} [partnerKey] - Partner key
|
|
333
342
|
*/
|
|
334
343
|
|
|
335
344
|
/**
|
|
336
|
-
* @typedef {'disconnected'|'ready'|'quote'|'trade'}
|
|
337
|
-
*/
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* @typedef {'quote'|'paused'|'progress'|'finished'|'error'} StellarBrokerClientEvent
|
|
345
|
+
* @typedef {'disconnected'|'ready'|'quote'|'trade'} ClientSessionStatus - Current client session status
|
|
341
346
|
*/
|
|
342
347
|
|
|
343
348
|
/**
|
|
344
|
-
* @typedef {
|
|
345
|
-
* @property {string} ts - Quote timestamp formatted as ISO date
|
|
346
|
-
* @property {string} sellingAsset - Asset to sell
|
|
347
|
-
* @property {string} buyingAsset - Asset to buy
|
|
348
|
-
* @property {number} slippageTolerance - Swap slippage tolerance
|
|
349
|
-
* @property {string} sellingAmount - Amount of the selling asset
|
|
350
|
-
* @property {string} [estimatedBuyingAmount] - Estimated amount of buyingAsset to receive
|
|
351
|
-
* @property {{selling: string, buying: string, path: string[]}} [directTrade] - Equivalent direct path_payment trade estimate
|
|
352
|
-
* @property {string} [error] - Error details from the server (for failed quotes)
|
|
349
|
+
* @typedef {'quote'|'paused'|'progress'|'finished'|'error'} StellarBrokerClientEvent - Event type generated by the client
|
|
353
350
|
*/
|
package/src/estimate.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import errors, {StellarBrokerError} from './errors.js'
|
|
2
2
|
import {validateQuoteRequest} from './quote-request.js'
|
|
3
|
+
import {QuoteResult} from './quote-result.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Request single swap quote estimate without trading
|
|
6
|
-
* @param {
|
|
7
|
-
* @return {Promise<
|
|
7
|
+
* @param {QuoteParams} params
|
|
8
|
+
* @return {Promise<QuoteResult>}
|
|
8
9
|
*/
|
|
9
10
|
export async function estimateSwap(params) {
|
|
10
11
|
const query = Object.entries(validateQuoteRequest(params))
|
|
@@ -15,7 +16,7 @@ export async function estimateSwap(params) {
|
|
|
15
16
|
const res = await fetch(url).then(r => r.json())
|
|
16
17
|
if (res.status !== 'success')
|
|
17
18
|
throw errors.quoteError(res.error || 'Quote not available')
|
|
18
|
-
return res
|
|
19
|
+
return new QuoteResult(res)
|
|
19
20
|
} catch (e) {
|
|
20
21
|
if (e instanceof StellarBrokerError)
|
|
21
22
|
throw e
|
package/src/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {Asset,
|
|
1
|
+
import {Asset, TransactionI} from "@stellar/stellar-sdk";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Client for StellarBroker service
|
|
5
5
|
*/
|
|
6
|
-
export
|
|
6
|
+
export class StellarBrokerClient {
|
|
7
7
|
/**
|
|
8
8
|
* @param {ClientInitializationParams} params
|
|
9
9
|
*/
|
|
@@ -20,9 +20,9 @@ export default class StellarBrokerClient {
|
|
|
20
20
|
*/
|
|
21
21
|
readonly network: string;
|
|
22
22
|
/**
|
|
23
|
-
* @type {
|
|
23
|
+
* @type {ClientSessionStatus}
|
|
24
24
|
*/
|
|
25
|
-
readonly status:
|
|
25
|
+
readonly status: ClientSessionStatus;
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Connect to the StellarBroker server
|
|
@@ -32,9 +32,9 @@ export default class StellarBrokerClient {
|
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Request swap quote
|
|
35
|
-
* @param {
|
|
35
|
+
* @param {QuoteParams} params - Quote parameters
|
|
36
36
|
*/
|
|
37
|
-
quote(params:
|
|
37
|
+
quote(params: QuoteParams): void;
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* Stop quotation/trading
|
|
@@ -43,8 +43,9 @@ export default class StellarBrokerClient {
|
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Confirm current quote and start trading
|
|
46
|
+
* @param {string} [account] - Trader account address (overrides value provided in the constructor)
|
|
46
47
|
*/
|
|
47
|
-
confirmQuote(): void;
|
|
48
|
+
confirmQuote(account?: string): void;
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
51
|
* Add event listener
|
|
@@ -76,9 +77,12 @@ export default class StellarBrokerClient {
|
|
|
76
77
|
/**
|
|
77
78
|
* Request single swap quote estimate without trading
|
|
78
79
|
*/
|
|
79
|
-
export function estimateSwap(params:
|
|
80
|
+
export function estimateSwap(params: QuoteParams): Promise<QuoteResult>;
|
|
80
81
|
|
|
81
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Quote request parameters provided by the client
|
|
84
|
+
*/
|
|
85
|
+
export interface QuoteParams {
|
|
82
86
|
/**
|
|
83
87
|
* Asset to sell
|
|
84
88
|
*/
|
|
@@ -97,64 +101,97 @@ export interface SwapQuoteParams {
|
|
|
97
101
|
slippageTolerance?: number
|
|
98
102
|
}
|
|
99
103
|
|
|
100
|
-
|
|
101
104
|
export interface ClientInitializationParams {
|
|
105
|
+
/**
|
|
106
|
+
* Authorization method, either account secret key or an authorization callback
|
|
107
|
+
*/
|
|
108
|
+
authorization: ClientAuthorizationParams;
|
|
102
109
|
/**
|
|
103
110
|
* Trader account address
|
|
104
111
|
*/
|
|
105
|
-
account
|
|
112
|
+
account?: string;
|
|
106
113
|
/**
|
|
107
114
|
* Partner key
|
|
108
115
|
*/
|
|
109
116
|
partnerKey?: string;
|
|
110
|
-
/**
|
|
111
|
-
* Authorization method, either account secret key or an authorization callback
|
|
112
|
-
*/
|
|
113
|
-
authorization: ClientAuthorizationParams;
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Current client session status
|
|
121
|
+
*/
|
|
122
|
+
export type ClientSessionStatus = "disconnected" | "ready" | "quote" | "trade";
|
|
117
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Event type generated by the client
|
|
126
|
+
*/
|
|
118
127
|
export type StellarBrokerClientEvent = "quote" | "progress" | "paused" | "finished" | "error";
|
|
119
128
|
|
|
120
|
-
|
|
129
|
+
/**
|
|
130
|
+
* Result status code returned by the server
|
|
131
|
+
*/
|
|
132
|
+
export type QuoteResultStatus = "unfeasible" | "rejected" | "success";
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Quote received from the server
|
|
136
|
+
*/
|
|
137
|
+
export interface QuoteResult {
|
|
121
138
|
/**
|
|
122
|
-
* Quote timestamp
|
|
139
|
+
* Quote timestamp
|
|
123
140
|
*/
|
|
124
|
-
ts:
|
|
141
|
+
readonly ts: Date,
|
|
142
|
+
/**
|
|
143
|
+
* Quote status code
|
|
144
|
+
*/
|
|
145
|
+
readonly status: QuoteResultStatus;
|
|
125
146
|
/**
|
|
126
147
|
* Asset to sell
|
|
127
148
|
*/
|
|
128
|
-
sellingAsset: string;
|
|
149
|
+
readonly sellingAsset: string;
|
|
129
150
|
/**
|
|
130
151
|
* Asset to buy
|
|
131
152
|
*/
|
|
132
|
-
buyingAsset: string;
|
|
153
|
+
readonly buyingAsset: string;
|
|
133
154
|
/**
|
|
134
155
|
* Swap slippage tolerance
|
|
135
156
|
*/
|
|
136
|
-
slippageTolerance: number;
|
|
157
|
+
readonly slippageTolerance: number;
|
|
137
158
|
/**
|
|
138
159
|
* Amount of the selling asset
|
|
139
160
|
*/
|
|
140
|
-
sellingAmount: string;
|
|
161
|
+
readonly sellingAmount: string;
|
|
141
162
|
/**
|
|
142
163
|
* Estimated amount of buyingAsset to receive
|
|
143
164
|
*/
|
|
144
|
-
estimatedBuyingAmount?: string;
|
|
165
|
+
readonly estimatedBuyingAmount?: string;
|
|
145
166
|
/**
|
|
146
167
|
* Equivalent direct path_payment trade estimate
|
|
147
168
|
*/
|
|
148
|
-
directTrade?:
|
|
169
|
+
readonly directTrade?: QuoteDirectTradeResult;
|
|
170
|
+
/**
|
|
171
|
+
* Difference between quoted price and estimated direct trade
|
|
172
|
+
*/
|
|
173
|
+
readonly profit: string;
|
|
149
174
|
/**
|
|
150
175
|
* Error details from the server (for failed quotes)
|
|
151
176
|
*/
|
|
152
|
-
error?: string;
|
|
177
|
+
readonly error?: string;
|
|
153
178
|
}
|
|
154
179
|
|
|
155
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Emulated single `path_payment` trades result corresponding to the quote
|
|
182
|
+
*/
|
|
183
|
+
export interface QuoteDirectTradeResult {
|
|
184
|
+
/**
|
|
185
|
+
* Estimated amount to sell
|
|
186
|
+
*/
|
|
156
187
|
selling: string;
|
|
188
|
+
/**
|
|
189
|
+
* Estimated amount to buy
|
|
190
|
+
*/
|
|
157
191
|
buying: string;
|
|
192
|
+
/**
|
|
193
|
+
* Conversion path
|
|
194
|
+
*/
|
|
158
195
|
path: string[];
|
|
159
196
|
}
|
|
160
197
|
|
|
@@ -219,5 +256,5 @@ export class Mediator {
|
|
|
219
256
|
/**
|
|
220
257
|
* Dispose mediator account
|
|
221
258
|
*/
|
|
222
|
-
dispose(address:string): Promise<void>;
|
|
259
|
+
dispose(address: string): Promise<void>;
|
|
223
260
|
}
|
package/src/index.js
CHANGED
package/src/quote-request.js
CHANGED
|
@@ -2,7 +2,7 @@ import errors from './errors.js'
|
|
|
2
2
|
import {parseAsset} from './asset.js'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* @typedef {object}
|
|
5
|
+
* @typedef {object} QuoteParams - Quote request parameters provided by the client
|
|
6
6
|
* @property {string} sellingAsset - Asset to sell
|
|
7
7
|
* @property {string} buyingAsset - Asset to buy
|
|
8
8
|
* @property {string} [sellingAmount] - Amount of selling asset
|
|
@@ -10,8 +10,8 @@ import {parseAsset} from './asset.js'
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* @param {
|
|
14
|
-
* @return {
|
|
13
|
+
* @param {QuoteParams} params
|
|
14
|
+
* @return {QuoteParams}
|
|
15
15
|
*/
|
|
16
16
|
export function validateQuoteRequest(params) {
|
|
17
17
|
const {
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {fromStroops, toStroops} from './stroops.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {'unfeasible'|'rejected'|'success'} QuoteResultStatus - Result status code returned by the server
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {Object} QuoteDirectTradeResult - Emulated single `path_payment` trades result corresponding to the quote
|
|
9
|
+
* @property {string} selling - Estimated amount to sell
|
|
10
|
+
* @property {string} buying - Estimated amount to buy
|
|
11
|
+
* @property {string[]} path - Conversion path
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Quote received from the server
|
|
16
|
+
*/
|
|
17
|
+
export class QuoteResult {
|
|
18
|
+
/**
|
|
19
|
+
* @param {{}} result
|
|
20
|
+
* @package
|
|
21
|
+
*/
|
|
22
|
+
constructor(result) {
|
|
23
|
+
Object.assign(this, result)
|
|
24
|
+
if (result.estimatedBuyingAmount && result.directTrade) {
|
|
25
|
+
const profit = toStroops(result.estimatedBuyingAmount) - toStroops(result.directTrade.buying)
|
|
26
|
+
if (profit > 0) {
|
|
27
|
+
this.profit = fromStroops(profit)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
this.ts = new Date()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Quote timestamp
|
|
35
|
+
* @type {Date}
|
|
36
|
+
* @readonly
|
|
37
|
+
*/
|
|
38
|
+
ts
|
|
39
|
+
/**
|
|
40
|
+
* Quote status code
|
|
41
|
+
* @type {QuoteResultStatus}
|
|
42
|
+
* @readonly
|
|
43
|
+
*/
|
|
44
|
+
status
|
|
45
|
+
/**
|
|
46
|
+
* Asset to sell
|
|
47
|
+
* @type {string}
|
|
48
|
+
* @readonly
|
|
49
|
+
*/
|
|
50
|
+
sellingAsset
|
|
51
|
+
/**
|
|
52
|
+
* Asset to buy
|
|
53
|
+
* @type {string}
|
|
54
|
+
* @readonly
|
|
55
|
+
*/
|
|
56
|
+
buyingAsset
|
|
57
|
+
/**
|
|
58
|
+
* Swap slippage tolerance
|
|
59
|
+
* @type {number}
|
|
60
|
+
* @readonly
|
|
61
|
+
*/
|
|
62
|
+
slippageTolerance
|
|
63
|
+
/**
|
|
64
|
+
* Amount of the selling asset
|
|
65
|
+
* @type {string}
|
|
66
|
+
* @readonly
|
|
67
|
+
*/
|
|
68
|
+
sellingAmount
|
|
69
|
+
/**
|
|
70
|
+
* Estimated amount of buyingAsset to receive
|
|
71
|
+
* @type {string}
|
|
72
|
+
* @readonly
|
|
73
|
+
*/
|
|
74
|
+
estimatedBuyingAmount
|
|
75
|
+
/**
|
|
76
|
+
* Equivalent direct path_payment trade estimate
|
|
77
|
+
* @type {QuoteDirectTradeResult}
|
|
78
|
+
* @readonly
|
|
79
|
+
*/
|
|
80
|
+
directTrade
|
|
81
|
+
/**
|
|
82
|
+
* Difference between quoted price and estimated direct trade
|
|
83
|
+
* @type {string}
|
|
84
|
+
* @readonly
|
|
85
|
+
*/
|
|
86
|
+
profit = '0'
|
|
87
|
+
/**
|
|
88
|
+
* Error details from the server (for rejected quote requests)
|
|
89
|
+
* @type {string}
|
|
90
|
+
* @readonly
|
|
91
|
+
*/
|
|
92
|
+
error
|
|
93
|
+
}
|
package/src/tx-processor.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {hash,
|
|
1
|
+
import {hash, nativeToScVal, StrKey, TransactionBuilder, xdr} from '@stellar/stellar-sdk'
|
|
2
2
|
import errors from './errors.js'
|
|
3
3
|
|
|
4
|
+
const networkIdCache = {}
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* @param {StellarBrokerClient} client
|
|
6
8
|
* @param {{xdr: string, hash: string, networkFee: string, [confirmed]: boolean}} txRequest
|
|
@@ -51,8 +53,10 @@ async function authorizeInvocation(client, tx) {
|
|
|
51
53
|
/** @type {xdr.SorobanAddressCredentials} */
|
|
52
54
|
const addrAuth = auth.credentials().address()
|
|
53
55
|
addrAuth.signatureExpirationLedger(tx.ledgerBounds.maxLedger + 1)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
let networkId = networkIdCache[tx.networkPassphrase]
|
|
57
|
+
if (!networkId) {
|
|
58
|
+
networkId = networkIdCache[tx.networkPassphrase] = hash(Buffer.from(tx.networkPassphrase))
|
|
59
|
+
}
|
|
56
60
|
const preimage = xdr.HashIdPreimage.envelopeTypeSorobanAuthorization(
|
|
57
61
|
new xdr.HashIdPreimageSorobanAuthorization({
|
|
58
62
|
networkId,
|