Blockchain is a welcoming place. Some of my closest friends I have met only virtually, and know only because we own similar overpriced handdrawn avatars: you may know these as NFT's.

Maybe we like each other's NFT and want to swap; but blockchain has a dark side. Blockchain is terrifying. Once you click sign on a transaction, there is no going back. Blockchain is forever. So on the off-chance our trade goes awry, my beloved frog NFT would be lost forever.

So how are transactions secured on blockchain? Blockchain gains its security through lack of trust. Never trust the other party interacting with your smart contract. Never trust the other party in your trade.

These are the same principles guiding PinnacleSwap - a decentralized application built on the Stellar blockchain. We help users trade any Stellar asset, whether that be a stablecoin, NFT, or token, securely. Our smart contract serves as a "trusted third party" to the trade, not releasing assets until both parties have sent their proposed assets - trades are even possible asynchronously. Why trust our contract? Because it's opensource and easily auditable.

PinnacleSwap can swap from one asset to many, NFT for stablecoin and token and any combination of the above. PinnacleSwap is designed to be first and foremost, safe and easy to use. At any time in the process, users can return their assets. PinnacleSwap is absolutely free to use as well, while other platforms have a 2.5% fee yet processed over 5b in transactions thus far in September.

On Ethereum, OpenZepplin is a framework for smart contracts that supports in excess of 100b in volume every year. In the future, we hope PinnacleSwap is not only used directly in our frontend for user trades. For this reason, we have exposed an easy to use, free and open API for other developers - perhaps a defacto standard for cross asset swaps.


This project features over 500 lines of smart contract code, mostly aimed at security. The next few sections detail the implementations.


When a user first enters our site, they are logged in with Albedo (Stellar's version of Web3).

From there, a user can choose to cancel all their trades - this sends an API request (see API section below).

If a user would like to create a new trade, they sign a Trustlink for all wanted assets, alongside sending their proposed assets. The XDR is generated through the server-side API and signed with Albedo. A unique sha256 hash of the current timestamp alongside the assets traded is used. This hash is crucial, and referred to henceforth as tradeHash.

The tradeHash is used to access status, or add a second party to the trade. In addition, transactions are identified by their tradeHash in the memo.

Server-side, and API for other developers

tradeHash is used extensively in the backend in order to identify transactions.

In our API, the /startswap route takes a JSON body containing the following:

  "tradeHash": // unique sha256 hash to identify trade
  "initializerPubKey": // trade initializer public key
  "whitelistedAddresses": // keys allowed to trade (or null for no restrictions)
  "incomingAssets": // list of strings, assets sent by trade initiator
  "wantedAssets": // list of strings, assets desired by trade initiator
  "initialAmountList": // list of numbers, amount of asset sent by trade initiator (same length as incomingAssets)
  "wantedAmountList": // list of numbers, amount of asset desired by trade initiator (same length as wantedAssets)

From there, the escrow keys are used to sign Trustlinks to all incoming assets (both from the trade initializer and the second party). This is done server side to keep the escrow keys secure.

tradeHash will automatically be updated every time a transaction is sent with a corresponding memo, and the trade will be verified when all of initialAssets and wantedAssets are in the escrow account (alongside their corresponding amounts). There is no further action necessary for developers using our API.

We also provide a /status route to get a detailed status report of the trade, and a secure /resettrade route that sends all assets of a particular tradeHash back to their original sender.

All of our smart contract code is original - with the exception of 26 lines in ./contract/nft_swap/swap_api.js.

Built With

Share this project: