@stellar-broker/client 0.6.14 → 0.7.0

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.
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -1,2 +1,2 @@
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
- //# sourceMappingURL=stellarbroker.js.map
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("@stellar/stellar-sdk")):"function"==typeof define&&define.amd?define(["@stellar/stellar-sdk"],e):(t="undefined"!=typeof globalThis?globalThis:t||self).stellarbroker=e(t.stellarSdk)}(this,function(t){"use strict";class e extends Error{constructor(t,e){super(e),this.code=t}code=0}const s={invalidInitParam:t=>new e(1,`Invalid parameter value: "${t}"`),invalidAuthorizationParam:()=>new e(2,"Invalid authorization secret key or callback provided"),notConnected:()=>new e(3,"Client not connected to the server"),quoteNotSet:()=>new e(11,"Price quote not available"),quoteExpired:()=>new e(12,"Price quote expired"),quoteError:t=>new e(13,"Price quotation error: "+t),invalidQuoteParam:(t="asset",s)=>new e(14,`Invalid quote request parameter: "${t}". ${s}`),tradeInProgress:()=>new e(20,"Cannot change quote while trade is in progress"),invalidSwapTx:()=>new e(21,"Invalid swap transaction received from the server"),failedToSignTx:()=>new e(22,"Failed to sign received transaction"),unsupportedEventType:t=>new e(31,"Unknown event type: "+t),serverError:t=>new e(101,t)};function i(t,e,s){const i=new CustomEvent(t,{detail:e});return i[s||t]=e,i}const r={};async function o(e,i){let o;try{o=t.TransactionBuilder.fromXDR(i.xdr,e.network)}catch(t){throw s.invalidSwapTx()}if(!function(t,e){for(let s of e.operations){if("invokeHostFunction"===s.type)continue;if("pathPaymentStrictSend"!==s.type&&"pathPaymentStrictReceive"!==s.type)return!1;if(s.destination!==t.trader){if("pathPaymentStrictSend"!==s.type)return!1;if(s.source&&s.source!==t.trader)return!1}else if(s.source&&s.source!==s.destination||s.destination!==t.trader)return!1}return!0}(e,o))throw s.invalidSwapTx();if(o.operations[0].auth?.length>0){if(!o.signatures.length)return await async function(e,s){const i=s.operations[0].auth[0],o=i.credentials().address();o.signatureExpirationLedger(s.ledgerBounds.maxLedger+1);let n=r[s.networkPassphrase];n||(n=r[s.networkPassphrase]=t.hash(Buffer.from(s.networkPassphrase)));const a=t.xdr.HashIdPreimage.envelopeTypeSorobanAuthorization(new t.xdr.HashIdPreimageSorobanAuthorization({networkId:n,nonce:o.nonce(),invocation:i.rootInvocation(),signatureExpirationLedger:o.signatureExpirationLedger()})),u=t.hash(a.toXDR()),c=await e.authorization.authorize(u),h=t.StrKey.encodeEd25519PublicKey(o.address().accountId().value()),d=t.nativeToScVal({public_key:t.StrKey.decodeEd25519PublicKey(h),signature:c},{type:{public_key:["symbol",null],signature:["symbol",null]}});o.signature(t.xdr.ScVal.scvVec([d]))}(e,o),o=await n(e,o),o.toXDR()}else o=await n(e,o);let a=t.TransactionBuilder.buildFeeBumpTransaction(e.trader,i.networkFee,o,e.network);return a=await n(e,a),a.toXDR()}function n(e,i){return e.authorization.authorize(i).then(s=>{if("string"==typeof s&&(s=t.TransactionBuilder.fromXDR(s,e.network)),!s||s.signatures?.length<1)throw new Error("Transaction was not signed");return s}).catch(t=>{throw console.error(t),s.failedToSignTx()})}function a(e){if(e instanceof t.Asset)return e;if("xlm"===e||"XLM"===e||"native"===e.asset_type)return t.Asset.native();if(e.asset_type)return new t.Asset(e.asset_code,e.asset_issuer);const[s,i]=e.includes("-")?e.split("-"):e.split(":");return new t.Asset(s,i)}function u(t,e){if("string"==typeof t){if("XLM"===t||"xlm"===t||"native"===t)return"XLM";if(t.includes(":")){const[s,i]=t.split(":");return c(s),h(i,e),s+"-"+i}if(t.includes("-")){const[s,i]=t.split("-");return c(s),h(i,e),t}}throw s.invalidQuoteParam(e,"Invalid asset")}function c(t,e){if(!/^[a-zA-Z0-9]{1,12}$/.test(t))throw s.invalidQuoteParam(e,"Invalid asset code: "+(t||"missing"));return t}function h(e,i){if(!e||!t.StrKey.isValidEd25519PublicKey(e))throw s.invalidQuoteParam(i,"Invalid account address: "+(e||"missing"));return e}function d(t){const{sellingAsset:e,selling_asset:i,buyingAsset:r,buying_asset:o,sellingAmount:n,selling_amount:a,buyingAmount:c,buying_amount:h,slippageTolerance:d,slippage_tolerance:g,...f}=t,m={sellingAsset:u(e||i,"sellingAsset"),buyingAsset:u(r||o,"buyingAsset"),sellingAmount:l(n||a,"sellingAmount"),slippageTolerance:p(d||g||.02,"slippageTolerance")};if(m.buyingAsset===m.sellingAsset)throw s.invalidQuoteParam("buyingAsset","Buying asset can't be the same as selling asset");if(void 0===m.sellingAmount)throw s.invalidQuoteParam("sellingAmount",'Parameter "sellingAmount" parameter is required');return Object.assign(m,f),Object.freeze(m),m}function l(t,e){if(void 0===t)return;const i=parseFloat(t);if(isNaN(i)||i<=0)throw s.invalidQuoteParam(e,"Invalid asset amount: "+t);return t}function p(t,e){const i=parseFloat(t);if(isNaN(i))throw s.invalidQuoteParam(e,"Invalid slippage tolerance, number expected");if(i<0)throw s.invalidQuoteParam(e,"Slippage tolerance is too small, expected value >= 0");if(i>.5)throw s.invalidQuoteParam(e,"Slippage tolerance is too large, expected value < 0.5 (50%)");return i}function g(t,e=!1){if("number"==typeof t){if(0===t)return 0n;t=t.toFixed(7)}if("string"!=typeof t||!/^-?[\d.,]+$/.test(t)){if(e)throw new TypeError("Invalid number format");return 0n}try{let[s,i="0"]=t.split(".",2),r=!1;s.startsWith("-")&&(r=!0,s=s.slice(1));let o=10000000n*BigInt(s)+BigInt(i.slice(0,7).padEnd(7,"0"));if(r){if(o*=-1n,o<-0x8000000000000000n){if(e)throw new TypeError("Invalid number: Int64 overflow");return 0n}}else if(o>0xFFFFFFFFFFFFFFFFn){if(e)throw new TypeError("Invalid number: UInt64 overflow");return 0n}return o}catch(t){if(e){if(t.message.startsWith("Invalid number: "))throw t;throw new TypeError("Invalid number format")}return 0n}}function f(t){if(t<0n)throw new TypeError("Invalid amount: "+t.toString());const e=t%10000000n;let s=(t/10000000n).toString();return e&&(s+="."+e.toString().padStart(7,"0").replace(/0+$/,"")),s}class m{constructor(t){if(Object.assign(this,t),t.estimatedBuyingAmount&&t.directTrade){const e=g(t.estimatedBuyingAmount)-g(t.directTrade.buying);e>0&&(this.profit=f(e))}this.ts=new Date}ts;status;sellingAsset;buyingAsset;slippageTolerance;sellingAmount;estimatedBuyingAmount;directTrade;profit="0";error}class w{constructor(e){if("string"==typeof e)try{return void(this.authorization=t.Keypair.fromSecret(e))}catch(t){throw s.invalidAuthorizationParam()}else if("function"==typeof e)return void(this.authorization=e);throw s.invalidAuthorizationParam()}authorization;async authorize(e){return this.authorization instanceof t.Keypair?e.sign?(e.sign(this.authorization),e):this.authorization.sign(e):await function(t){if(!(t instanceof Promise)){if(!t)return Promise.reject();t=Promise.resolve(t)}return t}(this.authorization(e))}}const y=new Set(["quote","paused","progress","finished","error"]);function v(t){if(!y.has(t))throw s.unsupportedEventType(t)}const b="msb_";class A{constructor(e,s,i,r,o,n=5){if(!t.StrKey.isValidEd25519PublicKey(e))throw new Error("Invalid source account");this.source=e;try{this.sellingAsset=a(s)}catch(t){throw console.error(t),new Error("Invalid selling asset")}try{this.buyingAsset=a(i)}catch(t){throw console.error(t),new Error("Invalid buying asset")}try{this.sellingAmount=g(r)}catch(t){throw console.error(t),new Error("Invalid selling amount")}this.authorization=new w(o),this.reserveFeeAmount=n}source;sellingAsset;buyingAsset;sellingAmount;authorization;mediator;mediatorAddress;storagePrefix=b;reserveFeeAmount;get hasObsoleteMediators(){return this.constructor.hasObsoleteMediators(this.source,this.storagePrefix)}static hasObsoleteMediators(t,e=b){return Object.entries(localStorage).some(([s,i])=>i===t&&s.startsWith(e))}async disposeObsoleteMediators(){for(let[t,e]of Object.entries(localStorage))e===this.source&&t.startsWith(this.storagePrefix)&&await this.dispose(t.replace(this.storagePrefix,""))}static async disposeObsoleteMediators(t,e,s=b){const i=new A(t,"XLM","XLM","0",e);i.storagePrefix=s,await i.disposeObsoleteMediators()}async init(){const e=await this.loadAccount(this.source);if(!e)throw new Error("Mediator account doesn't exist on the ledger");const s=2+e.signers.length-1+[this.sellingAsset,this.buyingAsset].filter(t=>!t.isNative()).length,i=this.reserveFeeAmount+.5*s,r=[];this.mediator=t.Keypair.random(),this.mediatorAddress=this.mediator.publicKey();const{sellingAsset:o,buyingAsset:n}=this;if(o.isNative()){const s=this.sellingAmount+BigInt(1e7*i);if(g(k(e,o).balance)<s)throw new Error("Insufficient XLM balance for selling amount + potential trading fees");r.push(t.Operation.createAccount({source:this.source,destination:this.mediatorAddress,startingBalance:f(s)}))}else{const s=k(e,t.Asset.native());if(parseFloat(s.balance)<i)throw new Error("Insufficient XLM balance for potential trading fees");r.push(t.Operation.createAccount({source:this.source,destination:this.mediatorAddress,startingBalance:i.toString()}));const n=k(e,this.sellingAsset);if(!n||g(n.balance)<this.sellingAmount)throw new Error("Insufficient selling asset balance");r.push(t.Operation.changeTrust({source:this.mediatorAddress,asset:o})),r.push(t.Operation.payment({source:this.source,asset:o,destination:this.mediatorAddress,amount:f(this.sellingAmount)}))}if(n.isNative()||(r.push(t.Operation.changeTrust({source:this.mediatorAddress,asset:n})),k(e,n)||r.push(t.Operation.changeTrust({source:this.source,asset:n}))),e.signers.length>1){let{thresholds:s,signers:i}=e;i=i.filter(t=>"ed25519_public_key"===t.type),r.push(t.Operation.setOptions({source:this.mediatorAddress,inflationDest:this.source,homeDomain:"mediator.stellar.broker",masterWeight:Math.max(1,s.high_threshold,s.med_threshold),highThreshold:s.high_threshold,medThreshold:s.med_threshold,lowThreshold:s.low_threshold,signer:{ed25519PublicKey:i[0].key,weight:Math.max(1,i[0].weight)}}));for(let e=1;e<i.length;e++)r.push(t.Operation.setOptions({source:this.mediatorAddress,signer:{ed25519PublicKey:i[e].key,weight:Math.max(1,i[e].weight)}}))}else r.push(t.Operation.setOptions({source:this.mediatorAddress,homeDomain:"mediator.stellar.broker",masterWeight:1,highThreshold:1,medThreshold:1,lowThreshold:1,signer:{ed25519PublicKey:this.source,weight:1}}));return localStorage.setItem(this.storagePrefix+this.mediatorAddress,this.source),await this.buildAndSend(e,r),this.mediator.secret()}async dispose(e){e||(e=this.mediatorAddress);let s=await this.loadAccount(e);if(!s)throw localStorage.removeItem(this.storagePrefix+e),new Error(`Mediator account ${e} doesn't exist on the ledger`);if(!s.signers.find(t=>t.key===this.source))throw new Error(`${e} is not a mediator account for ${this.source}`);const i=[];for(const r of s.balances){if("native"===r.asset_type)continue;const s=a(r);r.balance>0&&i.push(t.Operation.payment({source:e,asset:s,destination:this.source,amount:r.balance})),i.push(t.Operation.changeTrust({source:e,asset:s,limit:"0"}))}i.push(t.Operation.accountMerge({source:e,destination:this.source})),this.mediatorAddress!==e&&(s=await this.loadAccount(this.source)),await this.buildAndSend(s,i),localStorage.removeItem(this.storagePrefix+e)}async buildAndSend(e,s,i){const r=new t.TransactionBuilder(e,{fee:"1000000",networkPassphrase:t.Networks.PUBLIC});r.setTimeout(t.TimeoutInfinite),i&&r.addMemo(t.Memo.text(i));for(const t of s)r.addOperation(t);let o=r.build();this.mediator&&o.sign(this.mediator),e.account_id===this.source&&(o=await this.authorization.authorize(o));if(!(await this.constructor.createHorizon().submitTransaction(o,{skipMemoRequiredCheck:!0})).successful)throw new Error("Failed to create mediator account")}async loadAccount(e){try{return await this.constructor.createHorizon().loadAccount(e)}catch(s){if(s instanceof t.NotFoundError)return console.warn(`Account ${e} doesn't exist on the ledger`),null;throw console.error(s),s}}static createHorizon(){return new t.Horizon.Server("https://horizon.stellar.org")}}function k(t,e){return t.balances.find(t=>e.isNative()?"native"===t.asset_type:t.asset_code===e.code&&t.asset_issuer===e.issuer)}return{StellarBrokerClient:class{constructor(e){this.partnerKey=e.partnerKey,this.emitter=new EventTarget,this.network=t.Networks.PUBLIC,this.trader=e.account,e.authorization&&(this.authorization=new w(e.authorization))}uid;status="disconnected";socket;emitter;origin="https://api.stellar.broker";network="";quoteRequest;lastQuote;tradeQuote;partnerKey;authorization;trader;connect(){return this.socket?.readyState===WebSocket.OPEN?Promise.resolve(this):(this.socket=new WebSocket(this.origin+"/ws?partner="+encodeURIComponent(this.partnerKey)),this.socket.onmessage=this.processMessage.bind(this),this.socket.onclose=()=>{"disconnected"!==this.status&&(this.status="disconnected",this.notifyError(s.notConnected())),console.log("Connection closed")},this.socket.onerror=t=>console.error(t),new Promise((t,e)=>{const s=setTimeout(()=>e(this),2e3);this.onSocketOpen=()=>{this.status="ready",this.heartbeat(),this.onSocketOpen=void 0,clearTimeout(s),t(this)}}))}processMessage(t){const e=JSON.parse(t.data);switch(e.type){case"connected":this.uid=e.uid,this.onSocketOpen&&this.onSocketOpen(),"disconnected"===this.status&&(this.status="ready");break;case"quote":this.lastQuote=new m(e.quote),this.emitter.dispatchEvent(i("quote",this.lastQuote));break;case"paused":this.emitter.dispatchEvent(i("paused",{}));break;case"tx":if("trade"!==this.status)return void console.log("Received tx in a non-trading state",this.status,e);o(this,e).then(t=>{this.send({type:"tx",hash:e.hash,xdr:t})}).catch(t=>this.notifyError(t));break;case"stop":this.emitter.dispatchEvent(i("finished",{status:e.status,sold:e.sold,bought:e.bought},"result")),this.status="ready",this.tradeQuote=void 0;break;case"progress":this.emitter.dispatchEvent(i("progress",{sold:e.sold,bought:e.bought},"status"));break;case"ping":e.uid===this.uid&&(this.heartbeat(),this.send({type:"pong",uid:this.uid}));break;case"error":this.stop(),this.notifyError(e.error);break;default:console.log("Unknown message type: "+e.type)}}quote(t){if("trade"===this.status)throw s.tradeInProgress();this.quoteRequest=d(t),this.status="quote",this.connect().then(()=>{this.status="quote",this.send({type:"quote",...this.quoteRequest})})}confirmQuote(e,i){if("disconnected"===this.status)throw s.notConnected();if("trade"===this.status)throw s.tradeInProgress();if("quote"!==this.status||!this.lastQuote)throw s.quoteNotSet();if(new Date-this.lastQuote.ts>1e4)throw s.quoteExpired();if("success"!==this.lastQuote.status)throw s.quoteError(this.lastQuote.error||"quote not available");e&&(this.trader=e),i&&(this.authorization=new w(i));const{trader:r}=this;if(!r||!t.StrKey.isValidEd25519PublicKey(r))throw s.invalidQuoteParam("account","Invalid trader account address: "+(r||"missing"));if(!this.authorization)throw s.invalidQuoteParam("authorization","Client authorization not provided");this.tradeQuote=this.lastQuote,this.send({type:"trade",account:r}),this.status="trade"}stop(){"trade"!==this.status&&"quote"!==this.status||(this.send({type:"stop"}),this.tradeQuote=void 0,this.status="ready")}send(t){this.socket.send(JSON.stringify(t))}heartbeat(){clearTimeout(this.pingHandler),this.pingHandler=setTimeout(()=>{console.warn("Lost connection with the server"),this.socket.close()},7e3)}on(t,e){v(t),this.emitter.addEventListener(t,e)}once(t,e){v(t),this.emitter.addEventListener(t,e,{once:!0})}off(t,e){v(t),this.emitter.removeEventListener(t,e)}close(){try{this.status="disconnected",this.socket.close()}catch(t){}}notifyError(t){console.error(t);try{this.emitter.dispatchEvent(i("error",t instanceof Error?t.message:t))}catch(t){console.error(t)}}},estimateSwap:async function(t){const i=Object.entries(d(t)).filter(t=>void 0!==t[1]).map(([t,e])=>encodeURIComponent(t)+"="+encodeURIComponent(e)),r=(t.origin||"https://api.stellar.broker")+"/quote?"+i.join("&");try{const t=await fetch(r).then(t=>t.json());if("success"!==t.status)throw s.quoteError(t.error||"Quote not available");return new m(t)}catch(t){if(t instanceof e)throw t;throw s.quoteError("Failed to fetch quote")}},Mediator:A}});
2
+ //# sourceMappingURL=stellarbroker.js.map
@@ -1 +1 @@
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,MCgVZ,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 if (params.authorization) {\n this.authorization = new AuthorizationWrapper(params.authorization)\n }\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 * @param {ClientAuthorizationParams} [authorization] - Authorization params (overrides value provided in the constructor)\n */\n confirmQuote(account, authorization) {\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 if (authorization) {\n this.authorization = new AuthorizationWrapper(authorization)\n }\n const {trader} = this\n if (!trader || !StrKey.isValidEd25519PublicKey(trader)) //ensure that a trader account address provided\n throw errors.invalidQuoteParam('account', 'Invalid trader account address: ' + (!trader ? 'missing' : trader))\n if (!this.authorization)\n throw errors.invalidQuoteParam('authorization', 'Client authorization not provided')\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 {string} [partnerKey] - Partner key\n * @property {string} [account] - Trader account address\n * @property {ClientAuthorizationParams} [authorization] - Authorization method, either account secret key or an authorization callback\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":""}
1
+ {"version":3,"file":"stellarbroker.js","sources":["../src/errors.js","../src/events.js","../src/tx-processor.js","../src/asset.js","../src/quote-request.js","../src/stroops.js","../src/quote-result.js","../src/authorization.js","../src/client.js","../src/mediator.js","../src/bundle.js","../src/estimate.js"],"sourcesContent":["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 {hash, nativeToScVal, StrKey, TransactionBuilder, xdr} from '@stellar/stellar-sdk'\nimport errors from './errors.js'\n\nconst networkIdCache = {}\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 let networkId = networkIdCache[tx.networkPassphrase]\n if (!networkId) {\n networkId = networkIdCache[tx.networkPassphrase] = hash(Buffer.from(tx.networkPassphrase))\n }\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 {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} QuoteParams - Quote request parameters provided by the client\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 {QuoteParams} params\n * @return {QuoteParams}\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}","/**\r\n * Convert arbitrary stringified amount to int64 representation\r\n * @param {string|number} value\r\n * @param {boolean} throwIfInvalid\r\n * @return {BigInt}\r\n */\r\nexport function toStroops(value, throwIfInvalid = false) {\r\n if (typeof value === 'number') {\r\n if (value === 0)\r\n return 0n\r\n value = value.toFixed(7)\r\n }\r\n if (typeof value !== 'string' || !/^-?[\\d.,]+$/.test(value)) {\r\n if (throwIfInvalid)\r\n throw new TypeError('Invalid number format')\r\n return 0n\r\n }\r\n try {\r\n let [int, decimal = '0'] = value.split('.', 2)\r\n let negative = false\r\n if (int.startsWith('-')) {\r\n negative = true\r\n int = int.slice(1)\r\n }\r\n let res = BigInt(int) * 10000000n + BigInt(decimal.slice(0, 7).padEnd(7, '0'))\r\n if (negative) {\r\n res *= -1n\r\n if (res < -0x8000000000000000n) {//overflow\r\n if (throwIfInvalid)\r\n throw new TypeError('Invalid number: Int64 overflow')\r\n return 0n\r\n }\r\n } else if (res > 0xFFFFFFFFFFFFFFFFn) {//overflow\r\n if (throwIfInvalid)\r\n throw new TypeError('Invalid number: UInt64 overflow')\r\n return 0n\r\n }\r\n return res\r\n } catch (e) {\r\n if (throwIfInvalid) {\r\n if (e.message.startsWith('Invalid number: '))\r\n throw e\r\n throw new TypeError('Invalid number format')\r\n }\r\n return 0n\r\n }\r\n}\r\n\r\n\r\n/**\r\n * Format int64 value representation in stroops as string\r\n * @param {bigint} valueInStroops\r\n * @return {string}\r\n */\r\nexport function fromStroops(valueInStroops) {\r\n if (valueInStroops < 0n)\r\n throw new TypeError('Invalid amount: ' + valueInStroops.toString())\r\n const int = valueInStroops / 10000000n\r\n const fract = valueInStroops % 10000000n\r\n let res = int.toString()\r\n if (fract) {\r\n res += '.' + fract.toString().padStart(7, '0').replace(/0+$/, '')\r\n }\r\n return res\r\n}","import {fromStroops, toStroops} from './stroops.js'\r\n\r\n/**\r\n * @typedef {'unfeasible'|'rejected'|'success'} QuoteResultStatus - Result status code returned by the server\r\n */\r\n\r\n/**\r\n * @typedef {Object} QuoteDirectTradeResult - Emulated single `path_payment` trades result corresponding to the quote\r\n * @property {string} selling - Estimated amount to sell\r\n * @property {string} buying - Estimated amount to buy\r\n * @property {string[]} path - Conversion path\r\n */\r\n\r\n/**\r\n * Quote received from the server\r\n */\r\nexport class QuoteResult {\r\n /**\r\n * @param {{}} result\r\n * @package\r\n */\r\n constructor(result) {\r\n Object.assign(this, result)\r\n if (result.estimatedBuyingAmount && result.directTrade) {\r\n const profit = toStroops(result.estimatedBuyingAmount) - toStroops(result.directTrade.buying)\r\n if (profit > 0) {\r\n this.profit = fromStroops(profit)\r\n }\r\n }\r\n this.ts = new Date()\r\n }\r\n\r\n /**\r\n * Quote timestamp\r\n * @type {Date}\r\n * @readonly\r\n */\r\n ts\r\n /**\r\n * Quote status code\r\n * @type {QuoteResultStatus}\r\n * @readonly\r\n */\r\n status\r\n /**\r\n * Asset to sell\r\n * @type {string}\r\n * @readonly\r\n */\r\n sellingAsset\r\n /**\r\n * Asset to buy\r\n * @type {string}\r\n * @readonly\r\n */\r\n buyingAsset\r\n /**\r\n * Swap slippage tolerance\r\n * @type {number}\r\n * @readonly\r\n */\r\n slippageTolerance\r\n /**\r\n * Amount of the selling asset\r\n * @type {string}\r\n * @readonly\r\n */\r\n sellingAmount\r\n /**\r\n * Estimated amount of buyingAsset to receive\r\n * @type {string}\r\n * @readonly\r\n */\r\n estimatedBuyingAmount\r\n /**\r\n * Equivalent direct path_payment trade estimate\r\n * @type {QuoteDirectTradeResult}\r\n * @readonly\r\n */\r\n directTrade\r\n /**\r\n * Difference between quoted price and estimated direct trade\r\n * @type {string}\r\n * @readonly\r\n */\r\n profit = '0'\r\n /**\r\n * Error details from the server (for rejected quote requests)\r\n * @type {string}\r\n * @readonly\r\n */\r\n error\r\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 {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 if (params.authorization) {\n this.authorization = new AuthorizationWrapper(params.authorization)\n }\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 * @param {ClientAuthorizationParams} [authorization] - Authorization params (overrides value provided in the constructor)\n */\n confirmQuote(account, authorization) {\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 if (authorization) {\n this.authorization = new AuthorizationWrapper(authorization)\n }\n const {trader} = this\n if (!trader || !StrKey.isValidEd25519PublicKey(trader)) //ensure that a trader account address provided\n throw errors.invalidQuoteParam('account', 'Invalid trader account address: ' + (!trader ? 'missing' : trader))\n if (!this.authorization)\n throw errors.invalidQuoteParam('authorization', 'Client authorization not provided')\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 {string} [partnerKey] - Partner key\n * @property {string} [account] - Trader account address\n * @property {ClientAuthorizationParams} [authorization] - Authorization method, either account secret key or an authorization callback\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","import {Asset, Keypair, Memo, Operation, TransactionBuilder, Horizon, Networks, StrKey, TimeoutInfinite, NotFoundError} from '@stellar/stellar-sdk'\nimport {fromStroops, toStroops} from './stroops.js'\nimport {convertToStellarAsset} from './asset.js'\nimport {AuthorizationWrapper} from './authorization.js'\n\nconst defaultStoragePrefix = 'msb_'\n\nexport class Mediator {\n /**\n * Create a trader mediator account instance for a given source account\n * @param {string} source - Creator account address\n * @param {string|Asset} sellingAsset - Identifier of the asset to sell\n * @param {string|Asset} buyingAsset - Identifier of the asset to buy\n * @param {string} sellingAmount - Asset amount to sell\n * @param {ClientAuthorizationParams} authorization - Authorization callback or secret key\n * @param {number} [reserveFeeAmount] - Amount reserved to cover tx fees (all unused funds will be refunded)\n */\n constructor(source, sellingAsset, buyingAsset, sellingAmount, authorization, reserveFeeAmount = 5) {\n if (!StrKey.isValidEd25519PublicKey(source))\n throw new Error('Invalid source account')\n this.source = source\n try {\n this.sellingAsset = convertToStellarAsset(sellingAsset)\n } catch (e) {\n console.error(e)\n throw new Error('Invalid selling asset')\n }\n try {\n this.buyingAsset = convertToStellarAsset(buyingAsset)\n } catch (e) {\n console.error(e)\n throw new Error('Invalid buying asset')\n }\n try {\n this.sellingAmount = toStroops(sellingAmount)\n } catch (e) {\n console.error(e)\n throw new Error('Invalid selling amount')\n }\n this.authorization = new AuthorizationWrapper(authorization)\n this.reserveFeeAmount = reserveFeeAmount\n }\n\n /**\n * Creator account address\n * @type {string}\n * @readonly\n */\n source\n /**\n * @type {Asset}\n * @readonly\n */\n sellingAsset\n /**\n * @type {Asset}\n * @readonly\n */\n buyingAsset\n /**\n * @type {bigint}\n * @readonly\n */\n sellingAmount\n /**\n * @type {AuthorizationWrapper}\n * @private\n */\n authorization\n /**\n * @type {Keypair}\n * @private\n */\n mediator\n /**\n * @type {string}\n * @readonly\n */\n mediatorAddress\n /**\n * Prefix of the mediator address record in the localStorage\n * @type {string}\n * @private\n */\n storagePrefix = defaultStoragePrefix\n /**\n * @type {number}\n * @private\n */\n reserveFeeAmount\n\n /**\n * Check if there are any non-disposed mediators that belong to lost swap sessions\n * @return {boolean}\n */\n get hasObsoleteMediators() {\n return this.constructor.hasObsoleteMediators(this.source, this.storagePrefix)\n }\n\n /**\n * Check if there are any non-disposed mediators that belong to lost swap sessions\n * @param {string} source - Initiator account that created a mediator\n * @param {string} [storagePrefix] - Local storage key prefix\n * @return {boolean}\n */\n static hasObsoleteMediators(source, storagePrefix = defaultStoragePrefix) {\n return Object.entries(localStorage).some(([key, initiator]) =>\n initiator === source && key.startsWith(storagePrefix))\n }\n\n /**\n * Retrieve funds from mediator accounts that belong to lost swap sessions\n * @return {Promise}\n */\n async disposeObsoleteMediators() { //TODO: deal with potential problems caused by concurrent swaps\n for (let [key, initiator] of Object.entries(localStorage)) {\n if (initiator === this.source && key.startsWith(this.storagePrefix)) {\n await this.dispose(key.replace(this.storagePrefix, ''))\n }\n }\n }\n\n /**\n * Retrieve funds from mediator accounts that belong to lost swap sessions\n * @param {string} source - Initiator account that created a mediator\n * @param {ClientAuthorizationParams} authorization - Authorization callback or secret key\n * @param {string} [storagePrefix] - Local storage key prefix\n * @return {Promise}\n */\n static async disposeObsoleteMediators(source, authorization, storagePrefix = defaultStoragePrefix) {\n const wrapper = new Mediator(source, 'XLM', 'XLM', '0', authorization)\n wrapper.storagePrefix = storagePrefix\n await wrapper.disposeObsoleteMediators()\n }\n\n /**\n * Create mediator account and deposit tokens to sell\n * @return {Promise<string>} - Newly created mediator secret key\n */\n async init() {\n const sourceAccount = await this.loadAccount(this.source)\n if (!sourceAccount)\n throw new Error('Mediator account doesn\\'t exist on the ledger')\n //calculate fees reserve + account entries reserve\n const subentries = 2 + sourceAccount.signers.length - 1 + [this.sellingAsset, this.buyingAsset].filter(a => !a.isNative()).length\n const feesReserve = this.reserveFeeAmount + 0.5 * subentries\n const ops = []\n //create new random keypair for the trade\n this.mediator = Keypair.random()\n this.mediatorAddress = this.mediator.publicKey()\n //create mediator account and deposit funds\n const {sellingAsset, buyingAsset} = this\n if (sellingAsset.isNative()) { //for XLM total amount should include fee reserves\n const amount = this.sellingAmount + BigInt(feesReserve * 10000000)\n //check available balance\n if (toStroops(findTrustline(sourceAccount, sellingAsset).balance) < amount)\n throw new Error('Insufficient XLM balance for selling amount + potential trading fees')\n //only create account is required for asset transfer\n ops.push(Operation.createAccount({\n source: this.source,\n destination: this.mediatorAddress,\n startingBalance: fromStroops(amount)\n }))\n } else {\n //check available XLM balance\n const xlmBalance = findTrustline(sourceAccount, Asset.native())\n if (parseFloat(xlmBalance.balance) < feesReserve)\n throw new Error('Insufficient XLM balance for potential trading fees')\n //create mediator account\n ops.push(Operation.createAccount({\n source: this.source,\n destination: this.mediatorAddress,\n startingBalance: feesReserve.toString() // for tx fees\n }))\n //check available XLM balance\n const sellingTrustline = findTrustline(sourceAccount, this.sellingAsset)\n if (!sellingTrustline || toStroops(sellingTrustline.balance) < this.sellingAmount)\n throw new Error('Insufficient selling asset balance')\n //TODO: check authorizations\n //create trustline for selling asset\n ops.push(Operation.changeTrust({\n source: this.mediatorAddress,\n asset: sellingAsset\n }))\n //transfer tokens to sell\n ops.push(Operation.payment({\n source: this.source,\n asset: sellingAsset,\n destination: this.mediatorAddress,\n amount: fromStroops(this.sellingAmount)\n }))\n }\n //create trustline for buying asset\n if (!buyingAsset.isNative()) {\n ops.push(Operation.changeTrust({\n source: this.mediatorAddress,\n asset: buyingAsset\n }))\n //if source account itself doesn't have trustline for buying asset\n if (!findTrustline(sourceAccount, buyingAsset)) {\n ops.push(Operation.changeTrust({\n source: this.source,\n asset: buyingAsset\n }))\n }\n }\n\n if (sourceAccount.signers.length > 1) { //multisig or delegated schema\n let {thresholds, signers} = sourceAccount\n signers = signers.filter(signer => signer.type === 'ed25519_public_key')\n //add source account as a signer\n ops.push(Operation.setOptions({\n source: this.mediatorAddress,\n inflationDest: this.source, //store source account to the inflation dest\n homeDomain: 'mediator.stellar.broker',\n masterWeight: Math.max(1, thresholds.high_threshold, thresholds.med_threshold), //own signer always has the highest weight\n highThreshold: thresholds.high_threshold,\n medThreshold: thresholds.med_threshold,\n lowThreshold: thresholds.low_threshold,\n signer: { //add first signer\n ed25519PublicKey: signers[0].key,\n weight: Math.max(1, signers[0].weight)\n }\n }))\n //add all other signers\n for (let i = 1; i < signers.length; i++) {\n ops.push(Operation.setOptions({\n source: this.mediatorAddress,\n signer: { //cope signers and weights\n ed25519PublicKey: signers[i].key,\n weight: Math.max(1, signers[i].weight)\n }\n }))\n }\n } else { //simple schema\n ops.push(Operation.setOptions({\n source: this.mediatorAddress,\n homeDomain: 'mediator.stellar.broker',\n masterWeight: 1,\n highThreshold: 1,\n medThreshold: 1,\n lowThreshold: 1,\n signer: { //add source account as a signer\n ed25519PublicKey: this.source,\n weight: 1\n }\n }))\n }\n\n //store the record in the localStorage\n localStorage.setItem(this.storagePrefix + this.mediatorAddress, this.source)\n //confirm tx\n await this.buildAndSend(sourceAccount, ops)\n //client will need mediator secret for trading\n return this.mediator.secret()\n }\n\n /**\n * Dispose mediator account\n * @param {string} [address]\n * @return {Promise}\n */\n async dispose(address) {\n if (!address) {\n address = this.mediatorAddress\n }\n //load account\n let mediatorAccount = await this.loadAccount(address)\n if (!mediatorAccount) {\n //remove reference from local storage only if account doesn't exist on the ledger\n localStorage.removeItem(this.storagePrefix + address)\n throw new Error(`Mediator account ${address} doesn't exist on the ledger`)\n }\n\n if (!mediatorAccount.signers.find(s => s.key === this.source))\n throw new Error(`${address} is not a mediator account for ${this.source}`)\n const ops = []\n //remove trustlines for each account balance\n for (const balance of mediatorAccount.balances) {\n if (balance.asset_type === 'native')\n continue //skip XLM trustline - merge will handle the transfer\n const asset = convertToStellarAsset(balance)\n //transfer remaining balance to the source account\n if (balance.balance > 0) {\n ops.push(Operation.payment({\n source: address,\n asset,\n destination: this.source,\n amount: balance.balance\n }))\n }\n //remove trustline\n ops.push(Operation.changeTrust({\n source: address,\n asset,\n limit: '0'\n }))\n }\n //merge\n ops.push(Operation.accountMerge({\n source: address,\n destination: this.source\n }))\n if (this.mediatorAddress !== address) {\n mediatorAccount = await this.loadAccount(this.source)\n }\n await this.buildAndSend(mediatorAccount, ops)\n //remove reference from local storage\n localStorage.removeItem(this.storagePrefix + address)\n }\n\n /**\n * @param {AccountResponse} account\n * @param {Operation[]} operations\n * @param {string} [memo]\n * @private\n */\n async buildAndSend(account, operations, memo) {\n //create builder\n const builder = new TransactionBuilder(account, {\n fee: '1000000',\n networkPassphrase: Networks.PUBLIC\n })\n builder.setTimeout(TimeoutInfinite)\n //add memo if needed\n if (memo) {\n builder.addMemo(Memo.text(memo))\n }\n //add operations\n for (const op of operations) {\n builder.addOperation(op)\n }\n //build tx\n let tx = builder.build()\n //sign it on behalf of the mediator account (if available)\n if (this.mediator) {\n tx.sign(this.mediator)\n }\n //request signature from the client (if required)\n if (account.account_id === this.source) {\n tx = await this.authorization.authorize(tx)\n }\n //execute the tx\n const res = await this.constructor.createHorizon().submitTransaction(tx, {skipMemoRequiredCheck: true})\n if (!res.successful)\n throw new Error('Failed to create mediator account')\n }\n\n /**\n * @param {string} address\n * @return {Promise<AccountResponse>}\n * @private\n */\n async loadAccount(address) {\n try {\n return await this.constructor.createHorizon().loadAccount(address)\n } catch (e) {\n if (e instanceof NotFoundError) {\n console.warn(`Account ${address} doesn't exist on the ledger`)\n return null\n }\n console.error(e)\n throw e\n }\n }\n\n /**\n * @return {HorizonServer}\n * @private\n */\n static createHorizon() {\n return new Horizon.Server('https://horizon.stellar.org')\n }\n}\n\n\n/**\n * @param {AccountResponse} account\n * @param {Asset} asset\n * @return {BalanceLine}\n */\nfunction findTrustline(account, asset) {\n return account.balances.find(b => asset.isNative() ?\n b.asset_type === 'native' :\n b.asset_code === asset.code && b.asset_issuer === asset.issuer\n )\n}","import {StellarBrokerClient} from './client.js'\r\nimport {estimateSwap} from './estimate.js'\r\nimport {Mediator} from './mediator.js'\r\n\r\nconst bundle = {StellarBrokerClient, estimateSwap, Mediator}\r\n\r\nexport default bundle","import errors, {StellarBrokerError} from './errors.js'\r\nimport {validateQuoteRequest} from './quote-request.js'\r\nimport {QuoteResult} from './quote-result.js'\r\n\r\n/**\r\n * Request single swap quote estimate without trading\r\n * @param {QuoteParams} params\r\n * @return {Promise<QuoteResult>}\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 new QuoteResult(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":["StellarBrokerError","Error","constructor","code","message","super","this","errors","invalidInitParam","param","invalidAuthorizationParam","notConnected","quoteNotSet","quoteExpired","quoteError","invalidQuoteParam","invalidParamName","details","tradeInProgress","invalidSwapTx","failedToSignTx","unsupportedEventType","type","serverError","buildEvent","data","key","evt","CustomEvent","detail","networkIdCache","async","processTxRequest","client","txRequest","tx","TransactionBuilder","fromXDR","xdr","network","e","swap","operations","destination","trader","source","validateTransaction","auth","length","signatures","addrAuth","credentials","address","signatureExpirationLedger","ledgerBounds","maxLedger","networkId","networkPassphrase","hash","Buffer","from","preimage","HashIdPreimage","envelopeTypeSorobanAuthorization","HashIdPreimageSorobanAuthorization","nonce","invocation","rootInvocation","payload","toXDR","signature","authorization","authorize","publicKey","StrKey","encodeEd25519PublicKey","accountId","value","sigScVal","nativeToScVal","public_key","decodeEd25519PublicKey","ScVal","scvVec","authorizeInvocation","signTx","wrapped","buildFeeBumpTransaction","networkFee","then","catch","console","error","convertToStellarAsset","asset","Asset","asset_type","native","asset_code","asset_issuer","issuer","includes","split","parseAsset","parameter","validateCode","validateAccount","test","account","isValidEd25519PublicKey","validateQuoteRequest","params","sellingAsset","selling_asset","buyingAsset","buying_asset","sellingAmount","selling_amount","buyingAmount","buying_amount","slippageTolerance","slippage_tolerance","other","res","parseAmount","parseSlippageTolerance","undefined","Object","assign","freeze","amount","parsed","parseFloat","isNaN","src","tolerance","toStroops","throwIfInvalid","toFixed","TypeError","int","decimal","negative","startsWith","slice","BigInt","padEnd","fromStroops","valueInStroops","toString","fract","padStart","replace","QuoteResult","result","estimatedBuyingAmount","directTrade","profit","buying","ts","Date","status","AuthorizationWrapper","Keypair","fromSecret","sign","callResult","Promise","reject","resolve","promisify","stellarBrokerEvents","Set","validateEventType","has","defaultStoragePrefix","Mediator","reserveFeeAmount","mediator","mediatorAddress","storagePrefix","hasObsoleteMediators","entries","localStorage","some","initiator","disposeObsoleteMediators","dispose","wrapper","init","sourceAccount","loadAccount","subentries","signers","filter","a","isNative","feesReserve","ops","random","findTrustline","balance","push","Operation","createAccount","startingBalance","xlmBalance","sellingTrustline","changeTrust","payment","thresholds","signer","setOptions","inflationDest","homeDomain","masterWeight","Math","max","high_threshold","med_threshold","highThreshold","medThreshold","lowThreshold","low_threshold","ed25519PublicKey","weight","i","setItem","buildAndSend","secret","mediatorAccount","removeItem","find","s","balances","limit","accountMerge","memo","builder","fee","Networks","PUBLIC","setTimeout","TimeoutInfinite","addMemo","Memo","text","op","addOperation","build","account_id","createHorizon","submitTransaction","skipMemoRequiredCheck","successful","NotFoundError","warn","Horizon","Server","b","StellarBrokerClient","partnerKey","emitter","EventTarget","uid","socket","origin","quoteRequest","lastQuote","tradeQuote","connect","readyState","WebSocket","OPEN","encodeURIComponent","onmessage","processMessage","bind","onclose","notifyError","log","onerror","confirm","expirationTimeout","onSocketOpen","heartbeat","clearTimeout","raw","JSON","parse","quote","dispatchEvent","send","sold","bought","stop","confirmQuote","stringify","pingHandler","close","on","callback","addEventListener","once","off","removeEventListener","estimateSwap","query","kv","map","url","join","fetch","r","json"],"mappings":"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"}
package/package.json CHANGED
@@ -1,34 +1,39 @@
1
1
  {
2
2
  "name": "@stellar-broker/client",
3
- "version": "0.6.14",
3
+ "version": "0.7.0",
4
4
  "description": "Client library for StellarBroker service",
5
5
  "author": "team@stellar.broker",
6
6
  "homepage": "https://stellar.broker",
7
7
  "license": "MIT",
8
8
  "type": "module",
9
- "main": "lib/index.js",
9
+ "main": "lib/stellarbroker.js",
10
10
  "module": "src/index.js",
11
11
  "types": "src/index.d.ts",
12
+ "exports": {
13
+ "types": "./src/index.d.ts",
14
+ "import": "./src/index.js",
15
+ "require": "./lib/stellarbroker.js"
16
+ },
12
17
  "scripts": {
13
- "test": "jest",
14
- "prepare": "webpack --mode=production --config webpack.config.cjs"
18
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
19
+ "prepublishOnly": "rollup -c"
15
20
  },
16
21
  "repository": {
17
22
  "type": "git",
18
23
  "url": "git+https://github.com/stellar-broker/client.git"
19
24
  },
20
25
  "peerDependencies": {
21
- "@stellar/stellar-sdk": ">=13"
26
+ "@stellar/stellar-sdk": ">=16"
22
27
  },
23
28
  "devDependencies": {
24
- "@babel/core": "^7.26.7",
25
- "@babel/preset-env": "^7.26.7",
26
- "babel-loader": "^9.2.1",
27
- "babel-jest": "^29.7.0",
28
- "jest": "^29.7.0",
29
- "typescript": "^5.7.3",
30
- "webpack": "^5.97.1",
31
- "webpack-cli": "^5.1.4",
32
- "ws": "^8.17.1"
33
- }
29
+ "@rollup/plugin-terser": "1.0.0",
30
+ "rollup": "4.62.2",
31
+ "jest": "^30.4.2",
32
+ "ws": "^8.21.1"
33
+ },
34
+ "files": [
35
+ "src/",
36
+ "lib/",
37
+ "!src/bundle.js"
38
+ ]
34
39
  }