DEV Community

Tonny Kayage for ClickPesa

Posted on • Updated on

Listening to payments (real-time) on your Stellar wallet

Listening to payments (real-time) on your Stellar wallet

Stellar is an open source, decentralized protocol for digital currency to fiat money low-cost transfers which allows cross-border payments between any pair of currencies.

A Stellar wallet is a digital wallet used to hold lumens & other assets as a digital currency. It consits of a public key and a secret key which in combination can work as an address to recieve and send funds from.

Why do we want to get notified of the latest payments incoming to our wallet

Lets say you have a service whereby you are utilizing stellar as one of your payment options. Inorder to confirm the status of a transfer you need to continously check the whether you have recieved your funds via Horizon.

We need to find a way to get notified of incoming payments.

Solution 1

Periodically retrieve an account's payments using an API request. By using the following GET request a user is able to retrieve payments related to the account_id/public_key.

Using a curl request:

curl "https://horizon.stellar.org/accounts/<account_id>/payments?limit="
Enter fullscreen mode Exit fullscreen mode

The above curl request gets the latest payments on specified account_id.

An example response is:

{
  "_links": {
    "self": {
      "href": "https://horizon.stellar.org/accounts/GCNL55IJTH2HX26HLNIGYD2JIQLTBAQL3SVPNZA6PXK7NAVHU423WOTE/payments?cursor=\u0026limit=10\u0026order=desc"
    },
    "next": {
      "href": "https://horizon.stellar.org/accounts/GCNL55IJTH2HX26HLNIGYD2JIQLTBAQL3SVPNZA6PXK7NAVHU423WOTE/payments?cursor=110694007436259329\u0026limit=10\u0026order=desc"
    },
    "prev": {
      "href": "https://horizon.stellar.org/accounts/GCNL55IJTH2HX26HLNIGYD2JIQLTBAQL3SVPNZA6PXK7NAVHU423WOTE/payments?cursor=119400713599217665\u0026limit=10\u0026order=asc"
    }
  },
  "_embedded": {
    "records": [
      {
        "_links": {
          "self": {
            "href": "https://horizon.stellar.org/operations/119400713599217665"
          },
          "transaction": {
            "href": "https://horizon.stellar.org/transactions/b9d7c534b5fa168570a5bffe0f2089de150d00bf8cbd19ec93e897c565958f3f"
          },
          "effects": {
            "href": "https://horizon.stellar.org/operations/119400713599217665/effects"
          },
          "succeeds": {
            "href": "https://horizon.stellar.org/effects?order=desc\u0026cursor=119400713599217665"
          },
          "precedes": {
            "href": "https://horizon.stellar.org/effects?order=asc\u0026cursor=119400713599217665"
          }
        },
        "id": "119400713599217665",
        "paging_token": "119400713599217665",
        "transaction_successful": true,
        "source_account": "GCNL55IJTH2HX26HLNIGYD2JIQLTBAQL3SVPNZA6PXK7NAVHU423WOTE",
        "type": "payment",
        "type_i": 1,
        "created_at": "2020-01-17T20:32:38Z",
        "transaction_hash": "b9d7c534b5fa168570a5bffe0f2089de150d00bf8cbd19ec93e897c565958f3f",
        "asset_type": "credit_alphanum4",
        "asset_code": "USD",
        "asset_issuer": "GDUKMGUGDZQK6YHYA5Z6AY2G4XDSZPSZ3SW5UN3ARVMO6QSRDWP5YLEX",
        "from": "GCNL55IJTH2HX26HLNIGYD2JIQLTBAQL3SVPNZA6PXK7NAVHU423WOTE",
        "to": "GASWJWFRYE55KC7MGANZMMRBK5NPXT3HMPDQ6SEXZN6ZPWYXVVYBFRTE",
        "amount": "84.9410878"
      },
      {
        "_links": {
          "self": {
            "href": "https://horizon.stellar.org/operations/117356420835532801"
          },
          "transaction": {
            "href": "https://horizon.stellar.org/transactions/c25dd84798076ee8ea126c78407d61c7e8f3efdf8739274f56b07a7029500b00"
          },
          "effects": {
            "href": "https://horizon.stellar.org/operations/117356420835532801/effects"
          },
          "succeeds": {
            "href": "https://horizon.stellar.org/effects?order=desc\u0026cursor=117356420835532801"
          },
          "precedes": {
            "href": "https://horizon.stellar.org/effects?order=asc\u0026cursor=117356420835532801"
          }
        },
        "id": "117356420835532801",
        "paging_token": "117356420835532801",
        "transaction_successful": true,
        "source_account": "GDV4KECLSZLKRVH4ZTWVAS4I3W2LPAPV66ADFFUZKGIVOTK6GMKGJT53",
        "type": "payment",
        "type_i": 1,
        "created_at": "2019-12-18T08:23:35Z",
        "transaction_hash": "c25dd84798076ee8ea126c78407d61c7e8f3efdf8739274f56b07a7029500b00",
        "asset_type": "native",
        "from": "GDV4KECLSZLKRVH4ZTWVAS4I3W2LPAPV66ADFFUZKGIVOTK6GMKGJT53",
        "to": "GCNL55IJTH2HX26HLNIGYD2JIQLTBAQL3SVPNZA6PXK7NAVHU423WOTE",
        "amount": "355.3887598"
      },
      {
        "_links": {
          "self": {
            "href": "https://horizon.stellar.org/operations/115354197276323841"
          },
          "transaction": {
            "href": "https://horizon.stellar.org/transactions/c09d4cee993d60d73c80f036666966738a26b8f3b25d7275b93fd995505b5e5b"
          },
          "effects": {
            "href": "https://horizon.stellar.org/operations/115354197276323841/effects"
          },
          "succeeds": {
            "href": "https://horizon.stellar.org/effects?order=desc\u0026cursor=115354197276323841"
          },
          "precedes": {
            "href": "https://horizon.stellar.org/effects?order=asc\u0026cursor=115354197276323841"
          }
        },
        "id": "115354197276323841",
        "paging_token": "115354197276323841",
        "transaction_successful": true,
        "source_account": "GDV4KECLSZLKRVH4ZTWVAS4I3W2LPAPV66ADFFUZKGIVOTK6GMKGJT53",
        "type": "payment",
        "type_i": 1,
        "created_at": "2019-11-18T19:59:40Z",
        "transaction_hash": "c09d4cee993d60d73c80f036666966738a26b8f3b25d7275b93fd995505b5e5b",
        "asset_type": "native",
        "from": "GDV4KECLSZLKRVH4ZTWVAS4I3W2LPAPV66ADFFUZKGIVOTK6GMKGJT53",
        "to": "GCNL55IJTH2HX26HLNIGYD2JIQLTBAQL3SVPNZA6PXK7NAVHU423WOTE",
        "amount": "688.4065454"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Disadvantages of this approach are:

  • The load on servers will increase exponentially as the number of users and transactions increase in the system. This means for each user in your system there must be a job to fetch the latest transactions after every defined duration of time.
  • You also run a risk of overloading the stellar netowrk with multiple requests.

Solution 2

As the heading of the article suggests the second solution involves listening to transactions as they happen. To make this happen we utilize the Stellar SDK which provides an event-stream that can be subscribed to inorder to recieve latest payment information regarding the users account.

The following is how this solution can be imoplemented:

First we install the required stellar-sdk dependency into our project by using the follwoing command:

yarn add stellar-sdk
Enter fullscreen mode Exit fullscreen mode

Secondly we import the stellar-sdk using the require keyword. Thereafter we initialize the server sdk using the horizon url before using it.

var StellarSdk = require("stellar-sdk");
var server = new StellarSdk.Server("https://horizon.stellar.org");

server
  .payments()
  .cursor('now')
  .stream({
      onmessage: (payment)=>{},
      onerror: (error)=>{}
  })
Enter fullscreen mode Exit fullscreen mode

Example result(s) coming from the event stream are as follows:

{
        "_links": {
          "self": {
            "href": "https://horizon.stellar.org/operations/115354197276323841"
          },
          "transaction": {
            "href": "https://horizon.stellar.org/transactions/c09d4cee993d60d73c80f036666966738a26b8f3b25d7275b93fd995505b5e5b"
          },
          "effects": {
            "href": "https://horizon.stellar.org/operations/115354197276323841/effects"
          },
          "succeeds": {
            "href": "https://horizon.stellar.org/effects?order=desc\u0026cursor=115354197276323841"
          },
          "precedes": {
            "href": "https://horizon.stellar.org/effects?order=asc\u0026cursor=115354197276323841"
          }
        },
        "id": "115354197276323841",
        "paging_token": "115354197276323841",
        "transaction_successful": true,
        "source_account": "GDV4KECLSZLKRVH4ZTWVAS4I3W2LPAPV66ADFFUZKGIVOTK6GMKGJT53",
        "type": "payment",
        "type_i": 1,
        "created_at": "2019-11-18T19:59:40Z",
        "transaction_hash": "c09d4cee993d60d73c80f036666966738a26b8f3b25d7275b93fd995505b5e5b",
        "asset_type": "native",
        "from": "GDV4KECLSZLKRVH4ZTWVAS4I3W2LPAPV66ADFFUZKGIVOTK6GMKGJT53",
        "to": "GCNL55IJTH2HX26HLNIGYD2JIQLTBAQL3SVPNZA6PXK7NAVHU423WOTE",
        "amount": "688.4065454"
}
Enter fullscreen mode Exit fullscreen mode

Advantages of this approach:

  • Scalable & Robust. It does not require additional resources if / when your transaction activity grows over time.
  • Get status of payments as they happen in real-time using the memo supplied in conjuction with the business process implemented.

Additional resources

Stellar Documentation

Top comments (2)

Collapse
 
alphaolomi profile image
Alpha Olomi

Do Clickpesa offer an api ? or api docs ?

Collapse
 
tkayage profile image
Tonny Kayage

We do, may i ask for which services are you requesting an API doc for?