# Node.js

### Getting started

This package acts as a typescript wrapper on top of the Ston.fi [Omniston protocol API](https://github.com/ston-fi/omniston-api) and provides RxJS styled observables on top of the WebSocket API connection

📦 **NPM Package**: [@ston-fi/omniston-sdk](https://www.npmjs.com/package/@ston-fi/omniston-sdk)

### Installation

#### via NPM

```sh
npm install @ston-fi/omniston-sdk
```

#### via YARN

```sh
yarn add @ston-fi/omniston-sdk
```

#### via PNPM

```sh
pnpm install @ston-fi/omniston-sdk
```

### Create an instance

Create an Omniston instance, specifying the API URL.

```ts
import { Omniston } from "@ston-fi/omniston-sdk";

const omniston = new Omniston({
  apiUrl: "wss://omni-ws.ston.fi",
});
```

The constructor takes the following parameters:

| Name     | Type                     | Description                                                                                                                                  |
| -------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `client` | `ApiClient \| undefined` | Optional. Provide this if you want to override the default API client. By default, this will be an `ApiClient` using `ReconnectingTransport` |
| `apiUrl` | `URL \| string`          | Omniston WebSocket API URL.                                                                                                                  |

#### Sandbox example (testing)

If you are developing or testing your integration, use the public sandbox environment instead of production.

```ts
import { Omniston } from "@ston-fi/omniston-sdk";

const omniston = new Omniston({
  apiUrl: "wss://omni-ws-sandbox.ston.fi",
});
```

> Sandbox is intended for development and integration testing only. Do not use sandbox in production applications.

### Send a quote request

Send a request for quote to swap an asset to another asset.

```ts
import { GaslessSettlement } from "@ston-fi/omniston-sdk";

omniston
  .requestForQuote({
    settlementMethods: [SettlementMethod.SETTLEMENT_METHOD_SWAP],
    askAssetAddress: {
      blockchain: Blockchain.TON,
      address: "EQA2kCVNwVsil2EM2mB0SkXytxCqQjS4mttjDpnXmwG9T6bO", // STON
    },
    bidAssetAddress: {
      blockchain: Blockchain.TON,
      address: "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs", // USDT
    },
    amount: {
      bidUnits: "1000000", // 1 USDT
    },
    settlementParams: {
      maxPriceSlippageBps: 0,
      gaslessSettlement: GaslessSettlement.GASLESS_SETTLEMENT_POSSIBLE,
      maxOutgoingMessages: 4, // default for TON
      flexibleReferrerFee: true, // allow lower referrer fee if resolver improves the quote
    },
  })
  .subscribe((quoteResponseEvent) => {
    switch (quoteResponseEvent.type) {
      case 'ack': {
        // Quote request acknowledged
        const { rfqId } = quoteResponseEvent;
        console.log(`Quote request acknowledged with ID: ${rfqId}`);
        break;
      }
      case 'quoteUpdated': {
        // Quote received
        const { quote, rfqId } = quoteResponseEvent;
        console.log(`Quote updated for request ${rfqId}`);
        // Process the quote...
        break;
      }
      case 'unsubscribed': {
        const { rfqId } = quoteResponseEvent;
        console.log(`Unsubscribed from quote request ${rfqId}`);
        break;
      }
    }
  });
```

A `QuoteRequest` has the following properties:

| Name                | Type                                           | Description                                                                              |
| ------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `settlementMethods` | `SettlementMethod[]`                           | Supported methods of swap settlement                                                     |
| `askAssetAddress`   | `Address`                                      | Blockchain-specific address of ask asset                                                 |
| `bidAssetAddress`   | `Address`                                      | Blockchain-specific address of bid asset                                                 |
| `amount`            | `{ bidUnits: string } \| { askUnits: string }` | Either the amount of bid asset or ask asset                                              |
| `amount.bidUnits`   | `string`                                       | The amount of bid asset the trader wants to pay, including all fees, in base asset units |
| `amount.askUnits`   | `string`                                       | The amount of ask asset the trader wants to get after all fees, in base asset units      |
| `referrerAddress`   | `Address \| undefined`                         | The address of referrer that will receive the fees                                       |
| `referrerFeeBps`    | `number \| undefined`                          | The amount of fees required by the referrer in basis points (1/10000 or 0.01%)           |
| `settlementParams`  | `RequestSettlementParams \| undefined`         | Additional parameters of RFQ related to settlement. See the table below.                 |

**RequestSettlementParams**

| Name                     | Type                           | Description                                                                                                                                                                                                                                                                                                |
| ------------------------ | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `max_price_slippage_bps` | number \| undefined            | Maximum price slippage, in basis points (0.01%). For example, 100 = 1% slippage. Set to 0 to use recommended slippage.                                                                                                                                                                                     |
| `gasless_settlement`     | GaslessSettlement \| undefined | Gasless settlement preference. Options: `GASLESS_SETTLEMENT_PROHIBITED` (no gasless), `GASLESS_SETTLEMENT_POSSIBLE` (allow gasless), `GASLESS_SETTLEMENT_REQUIRED` (require gasless).                                                                                                                      |
| `max_outgoing_messages`  | number \| undefined            | Maximum number of outgoing messages supported by the wallet. For TON blockchain, this defaults to 4 if omitted.                                                                                                                                                                                            |
| `flexible_referrer_fee`  | boolean \| undefined           | Set to `true` to let resolvers lower the effective referrer fee below `referrerFeeBps` when offering a better rate. Defaults to `false`. In SDKs, pass this as `flexibleReferrerFee`. See [Flexible Referrer Fee](https://docs.ston.fi/developer-section/referral-fees#flexible-referrer-fee) for details. |

**Note**: Some parameters in `RequestSettlementParams` may only be relevant for certain blockchains or certain settlement methods. If your settlement method or wallet does not require them, you can omit them or set them to default values.

**Gasless Settlement Options**:

* `GASLESS_SETTLEMENT_PROHIBITED`: Disables gasless settlement completely
* `GASLESS_SETTLEMENT_POSSIBLE`: Allows gasless settlement if available (recommended)
* `GASLESS_SETTLEMENT_REQUIRED`: Forces gasless settlement (will fail if not available)

The server returns `Observable<QuoteResponseEvent>`, which is a stream of quote updates.

A `QuoteResponseEvent` might be one of the following:

* `{ type: "ack"; rfqId: string; }` - Acknowledgment that the quote request was received
* `{ type: "quoteUpdated"; quote: Quote; rfqId: string; }` - A quote update (includes rfqId after acknowledgment)
* `{ type: "noQuote"; }`
* `{ type: "unsubscribed"; rfqId: string; }` - Unsubscribed from the quote stream (includes rfqId after acknowledgment)

A `Quote` has the following properties:

| Name                      | Type                   | Description                                                                                 |
| ------------------------- | ---------------------- | ------------------------------------------------------------------------------------------- |
| `quoteId`                 | `string`               | ID of the quote generated by the platform (32 characters)                                   |
| `resolverId`              | `string`               | ID of the resolver                                                                          |
| `resolverName`            | `string`               | Name of the resolver                                                                        |
| `bidAssetAddress`         | `Address`              | Blockchain-specific address of bid asset                                                    |
| `askAssetAddress`         | `Address`              | Blockchain-specific address of ask asset                                                    |
| `bidUnits`                | `string`               | The amount of bid asset the trader must pay, including all fees                             |
| `askUnits`                | `string`               | The amount of ask asset the trader will get after all fees                                  |
| `referrerAddress`         | `Address \| undefined` | The address of referrer that will receive the fees                                          |
| `referrerFeeAsset`        | `Address`              | The asset of the fees that the referrer will get                                            |
| `referrerFeeUnits`        | `string`               | The amount of fees that the referrer will get (in units of `referrerFeeAsset`)              |
| `protocolFeeAsset`        | `Address`              | The asset of the fees charged by the protocol                                               |
| `protocolFeeUnits`        | `string`               | The amount of fees charged by the protocol (in units of `protocolFeeAsset`).                |
| `quoteTimestamp`          | `number`               | The timestamp (UTC seconds) of Quote sent by resolver                                       |
| `tradeStartDeadline`      | `number`               | Max timestamp (UTC seconds) of start of the trade                                           |
| `gasBudget`               | `string`               | The amount of gas budget for the trade                                                      |
| `estimatedGasConsumption` | `string`               | Estimated amount of gas units that will be spent to perform the trade                       |
| `params`                  | `object \| undefined`  | Various parameters specific to the settlement method. See the source code for more details. |

### Build a transaction

Now that we have a quote, we should request a server to build a transaction to initiate the trade that the user can verify and sign.

```ts
const tx = await omniston.buildTransfer({
  quote,
  sourceAddress: {
    blockchain: Blockchain.TON,
    address: "", // sender wallet address on `offerBlockchain`
  },
  destinationAddress: {
    blockchain: Blockchain.TON,
    address: "", // receiver wallet address on `askBlockchain`
  },
  gasExcessAddress: {
    blockchain: Blockchain.TON,
    address: "", // the address that will receive the gas not spent by the trade
  },
  useRecommendedSlippage: true, // Use recommended slippage from the quote
});

const messages = tx.ton?.messages ?? [];
```

The `buildTransfer` method takes a `TransactionRequest` object as a parameter, having the following properties:

| Name                     | Type                   | Description                                                                            |
| ------------------------ | ---------------------- | -------------------------------------------------------------------------------------- |
| `quote`                  | `Quote`                | The valid quote received from `Omniston.requestForQuote`                               |
| `sourceAddress`          | `Address`              | The address on `offerBlockchain` that will send initial transaction to start the trade |
| `destinationAddress`     | `Address`              | The address on `askBlockchain` that will receive result of the trade                   |
| `gasExcessAddress`       | `Address \| undefined` | The address that will receive the gas not spent by the trade                           |
| `refundAddress`          | `Address \| undefined` | The address to which funds will be returned in case of an failure                      |
| `useRecommendedSlippage` | `boolean \| undefined` | Whether to use the recommended slippage from the quote. Defaults to false.             |

### Sign the transaction

You can send `messages` to any library of your choice. Take a look at our [transaction sending guide](https://docs.ston.fi/developer-section/common/transaction-sending) with examples of different popular packages

### Listen for trade status updates

After the user has signed and initiated the transaction, we can track the trade status.

```ts
const tradeStatus = omniston.trackTrade({
  quoteId: quote.quoteId,
  traderWalletAddress: {
    blockchain: Blockchain.TON,
    address: "", // sender wallet address on `offerBlockchain`
  },
  outgoingTxHash: "", // Replace with the actual outgoingTxHash
});

tradeStatus.subscribe((status) => {
  console.log(JSON.stringify(status));
});
```

The `trackTrade` method has the following parameters:

| Name                  | Type      | Description                                               |
| --------------------- | --------- | --------------------------------------------------------- |
| `quoteId`             | `string`  | ID of the quote received from `Omniston.requestFromQuote` |
| `traderWalletAddress` | `Address` | The address of trader's wallet that initiated transaction |
| `outgoingTxHash`      | `string`  | Hash of the transaction that initiated the trade          |

It returns `Observable<TradeStatus>`. For the different trade status values, see the source code. We are interested in the trade result enum which can be read from `status.tradeSettled?.result?` field. The enum has the following values:

| Name                            | Description                                                |
| ------------------------------- | ---------------------------------------------------------- |
| `TRADE_RESULT_FULLY_FILLED`     | The trade has been completed and fully filled.             |
| `TRADE_RESULT_PARTIALLY_FILLED` | The trade has been partially filled. Something went wrong. |
| `TRADE_RESULT_ABORTED`          | The trade has been aborted.                                |
| `TRADE_RESULT_UNKNOWN`          |                                                            |
| `UNRECOGNIZED`                  |                                                            |
