puffscoin / puffsswap.core

Decentralized JS library for secure cross-chain swaps. USDT<>BTC<>PUFFS<>PUFFS tokens (ERC20) via ipfs.js

Home Page:https://puffsswap.leafycauldronapothecary.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PuffsSwap Core

In-browser atomic swap protocol based on HTLC (Hash-time Locked Contracts)

THIS APPLICATION REMAINS UNDER ACTIVE DEVELOPMENT AND MAY BE SUBJECT TO SIGNIFICANT CHANGES

PuffsSwap is a decentralized exchange protocol (DEP) for crosschain atomic-swaps, based on HTLC. It is written on JavaScript and can be run through a web-browser or via NodeJS. Support is current between BTC<>LTC<>PUFFS<>PUFFSTOKENs

tags: HTLC, atomic swap, javascript, browser, crypto, bitcoin, puffscoin, erc20, puffscoin

Usage examples are located in examples directory.

Usage

Simplest config:

import Web3 from 'web3'
import bitcoin from 'bitcoinjs-lib'

import swapApp, { constants } from 'swap.app'
import SwapAuth from 'swap.auth'
import SwapRoom from 'swap.room'
import SwapOrders from 'swap.orders'
import { PuffsSwap, PuffsTokenSwap, BtcSwap } from 'swap.swaps'
import { PUFFS2BTC, BTC2PUFFS, PUFFSTOKEN2BTC, BTC2PUFFSTOKEN } from 'swap.flows'


const web3 = new Web3(new Web3.providers.HttpProvider('https://puffsnet.provider/<YOUR_KEY>'))

SwapApp.setup({
  network: 'mainnet',

  env: {
    web3,
    bitcoin,
    Ipfs: window.Ipfs,
    IpfsRoom: window.IpfsRoom,
    storage: window.localStorage,
  },

  services: [
    new SwapAuth({
      puffs: null,
      btc: null,
    }),
    new SwapRoom({
      EXPERIMENTAL: {
        pubsub: true,
      },
      config: {
        Addresses: {
          Swarm: [
            '/dns4/ws-star.discovery.libp2p.io/tcp/443/wss/p2p-websocket-star',
          ],
        },
      },
    }),
    new SwapOrders(),
  ],

  swaps: [
    new PuffsSwap({
      address: '0xe08907e0e010a339646de2cc56926994f58c4db2',
      abi: [ { "constant": false, "inputs": [ { "name": "_ownerAddress", "type": "address" } ], "name": "abort", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_participantAddress", "type": "address" } ], "name": "close", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_secretHash", "type": "bytes20" }, { "name": "_participantAddress", "type": "address" } ], "name": "createSwap", "outputs": [], "payable": true, "stateMutability": "payable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_participantAddress", "type": "address" } ], "name": "refund", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_ratingContractAddress", "type": "address" } ], "name": "setReputationAddress", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_participantAddress", "type": "address" } ], "name": "sign", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "payable": false, "stateMutability": "nonpayable", "type": "constructor" }, { "constant": false, "inputs": [ { "name": "_secret", "type": "bytes32" }, { "name": "_ownerAddress", "type": "address" } ], "name": "withdraw", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [ { "name": "_ownerAddress", "type": "address" } ], "name": "checkSign", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [ { "name": "_ownerAddress", "type": "address" }, { "name": "_participantAddress", "type": "address" } ], "name": "getInfo", "outputs": [ { "name": "", "type": "bytes32" }, { "name": "", "type": "bytes20" }, { "name": "", "type": "uint256" }, { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [ { "name": "_participantAddress", "type": "address" } ], "name": "getSecret", "outputs": [ { "name": "", "type": "bytes32" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "owner", "outputs": [ { "name": "", "type": "address" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [ { "name": "", "type": "address" }, { "name": "", "type": "address" } ], "name": "participantSigns", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "ratingContractAddress", "outputs": [ { "name": "", "type": "address" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [ { "name": "", "type": "address" }, { "name": "", "type": "address" } ], "name": "swaps", "outputs": [ { "name": "secret", "type": "bytes32" }, { "name": "secretHash", "type": "bytes20" }, { "name": "createdAt", "type": "uint256" }, { "name": "balance", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [ { "name": "_ownerAddress", "type": "address" }, { "name": "_participantAddress", "type": "address" } ], "name": "unsafeGetSecret", "outputs": [ { "name": "", "type": "bytes32" } ], "payable": false, "stateMutability": "view", "type": "function" } ],
      fetchBalance: (address) => request.fetchPuffsBalance(address),
    }),
    new BtcSwap({
      fetchBalance: (address) => request.fetchBtcBalance(address),
      fetchUnspents: (scriptAddress) => request.fetchBtcUnspents(scriptAddress),
      broadcastTx: (txRaw) => request.broadcastBtcTx(txRaw),
    }),
    new PuffsTokenSwap({
      name: constants.COINS.noxon,
      address: '0xBA5c6DC3CAcdE8EA754e47c817846f771944518F',
      abi: [{"constant":false,"inputs":[{"name":"_secret","type":"bytes32"},{"name":"_ownerAddress","type":"address"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_participantAddress","type":"address"}],"name":"getSecret","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_ratingContractAddress","type":"address"}],"name":"setReputationAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"participantSigns","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_ownerAddress","type":"address"}],"name":"abort","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"swaps","outputs":[{"name":"token","type":"address"},{"name":"secret","type":"bytes32"},{"name":"secretHash","type":"bytes20"},{"name":"createdAt","type":"uint256"},{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_secretHash","type":"bytes20"},{"name":"_participantAddress","type":"address"},{"name":"_value","type":"uint256"},{"name":"_token","type":"address"}],"name":"createSwap","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_ownerAddress","type":"address"}],"name":"checkSign","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_participantAddress","type":"address"}],"name":"close","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ratingContractAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_participantAddress","type":"address"}],"name":"sign","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_ownerAddress","type":"address"}],"name":"getBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_participantAddress","type":"address"}],"name":"refund","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"Sign","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"createdAt","type":"uint256"}],"name":"CreateSwap","type":"event"},{"anonymous":false,"inputs":[],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[],"name":"Close","type":"event"},{"anonymous":false,"inputs":[],"name":"Refund","type":"event"},{"anonymous":false,"inputs":[],"name":"Abort","type":"event"}],
      tokenAddress: '0x60c205722c6c797c725a996cf9cca11291f90749',
      tokenAbi: [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"getBurnPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"manager","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unlockEmission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"emissionlocked","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"lockEmission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"burnAll","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newManager","type":"address"}],"name":"changeManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"changeOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"emissionPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"addToReserve","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"burnPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"tokenAddress","type":"address"},{"name":"amount","type":"uint256"}],"name":"transferAnyERC20Token","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"NoxonInit","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"acceptManagership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":false,"name":"ethers","type":"uint256"},{"indexed":false,"name":"_emissionedPrice","type":"uint256"},{"indexed":false,"name":"amountOfTokens","type":"uint256"}],"name":"TokenBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":false,"name":"ethers","type":"uint256"},{"indexed":false,"name":"_burnedPrice","type":"uint256"},{"indexed":false,"name":"amountOfTokens","type":"uint256"}],"name":"TokenBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"etherReserved","type":"uint256"}],"name":"PuffsReserved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}],
      fetchBalance: (address) => puffscoinInstance.fetchTokenBalance(address),
    }),
    new PuffsTokenSwap({
      name: constants.COINS.swap,
      address: '0xBA5c6DC3CAcdE8EA754e47c817846f771944518F',
      abi: [{"constant":false,"inputs":[{"name":"_secret","type":"bytes32"},{"name":"_ownerAddress","type":"address"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_participantAddress","type":"address"}],"name":"getSecret","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_ratingContractAddress","type":"address"}],"name":"setReputationAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"participantSigns","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_ownerAddress","type":"address"}],"name":"abort","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"swaps","outputs":[{"name":"token","type":"address"},{"name":"secret","type":"bytes32"},{"name":"secretHash","type":"bytes20"},{"name":"createdAt","type":"uint256"},{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_secretHash","type":"bytes20"},{"name":"_participantAddress","type":"address"},{"name":"_value","type":"uint256"},{"name":"_token","type":"address"}],"name":"createSwap","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_ownerAddress","type":"address"}],"name":"checkSign","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_participantAddress","type":"address"}],"name":"close","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ratingContractAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_participantAddress","type":"address"}],"name":"sign","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_ownerAddress","type":"address"}],"name":"getBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_participantAddress","type":"address"}],"name":"refund","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"Sign","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"createdAt","type":"uint256"}],"name":"CreateSwap","type":"event"},{"anonymous":false,"inputs":[],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[],"name":"Close","type":"event"},{"anonymous":false,"inputs":[],"name":"Refund","type":"event"},{"anonymous":false,"inputs":[],"name":"Abort","type":"event"}],
      tokenAddress: '0x60c205722c6c797c725a996cf9cca11291f90749',
      tokenAbi: [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"getBurnPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"manager","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unlockEmission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"emissionlocked","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"lockEmission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"burnAll","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newManager","type":"address"}],"name":"changeManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"changeOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"emissionPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"addToReserve","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"burnPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"tokenAddress","type":"address"},{"name":"amount","type":"uint256"}],"name":"transferAnyERC20Token","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"NoxonInit","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"acceptManagership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":false,"name":"ethers","type":"uint256"},{"indexed":false,"name":"_emissionedPrice","type":"uint256"},{"indexed":false,"name":"amountOfTokens","type":"uint256"}],"name":"TokenBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":false,"name":"ethers","type":"uint256"},{"indexed":false,"name":"_burnedPrice","type":"uint256"},{"indexed":false,"name":"amountOfTokens","type":"uint256"}],"name":"TokenBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"etherReserved","type":"uint256"}],"name":"EtherReserved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}],
      fetchBalance: (address) => puffscoinInstance.fetchTokenBalance(address),
    }),
  ],

  flows: [
    PUFFS2BTC,
    BTC2PUFFS,
    PUFFSTOKEN2BTC(constants.COINS.noxon),
    BTC2PUFFSTOKEN(constants.COINS.noxon),
  ],
})
import SwapApp, { constants } from 'swap.app'


SwapApp.services.orders.create({
  buyCurrency: constants.COINS.puffs,
  sellCurrency: constants.COINS.btc,
  buyAmount: 10,
  sellAmount: 1,
})

SwapApp.services.orders.getMyOrders() returns

[
  {
    id: '',

  }
]

[swap.app] SwapApp

SwapApp is singleton!

Configure params

Option Value Description
network 'mainnet' or 'testnet' (default)
env Map of environments Environment for API. Available env names: web3, bitcoin, Ipfs (required), IpfsRoom (required), storage (default: window.localStorage) Usage SwapApp.env.{envName}
services Array of service instances Usage SwapApp.services.{serviceName}
swaps Array of swap instances All standard swaps stored in swap.swaps package
flows Array of flow classes All standard flows stored in swap.flows package

Public props

Prop name Description
network
env
services
swaps
flows

Public methods

Method Description
isMainNet() Returns true if SwapApp.network === 'mainnet'
isTestNet() Returns true if SwapApp.network === 'testnet'

* SwapApp Services

Each service class should extend swap.app/ServiceInterface

class ServiceInterface {

  // _constructor for aggregation
  _constructor() {
    // service name, within it will be stored in SwapApp.services
    this._serviceName     = null
    this._dependsOn       = []
    this._spyHandlers     = []
  }

  constructor() {
    this._constructor()
  }

  _waitRelationsResolve() {
    if (this._dependsOn && this._dependsOn.length) {
      const dependsOnMap = {}

      this._dependsOn.forEach((Service) => {
        dependsOnMap[Service.name] = {
          initialized: false,
        }
        SwapApp.services[Service.name]._addWaitRelationHandler(() => {
          this._dependsOn[Service.name].initialized = true

          const areAllExpectsInitialized = Object.keys(this._dependsOn).every((serviceName) => (
            this._dependsOn[serviceName].initialized
          ))

          if (areAllExpectsInitialized) {
            this.initService()
          }
        })
      })

      this._dependsOn = dependsOnMap
    }
  }

  _addWaitRelationHandler(handler) {
    this._spyHandlers.push(handler)
  }

  _tryInitService() {
    if (!this._dependsOn) {
      this.initService()
      this._spyHandlers.forEach((handler) => handler())
      this._spyHandlers = []
    }
  }

  initService() {
    // init service on SwapApp mounting
  }
}

This interface allows services to be mounted in right order (to not care of services position in setup array). For example swap.orders depends on swap.room, so it must wait until swap.room be mounted in SwapApp.services.

[swap.auth] SwapApp.services.auth

The service for authentication and storing auth data. Currently contains puffs and btc

new SwapAuth({
  puffs: null,
  btc: null,
  ...
})

You can pass null or private key as value. If null passed new private key will be created, this key will be saved in SwapApp.env.storage by key {network}:{coinName}:privateKey - for network: mainnet and coin puffs it will be mainnet:puffs:privateKey

Public props

Prop name Description
accounts

Public methods

Method Description
getPublicData() Returns { address, publicKey } for each coin passed on initialization

* Extension

To extend auth service with new coins need to create new file with coin name (use puffs.js / btc.js as example) and add coin name to swap.app/constants/COINS.js

[swap.room] SwapApp.services.room

Wrapper over ipfs-pubsub-room package. This service provides a room based on an IPFS pub-sub channel. Emits membership events, listens for messages, broadcast and direct messages to peers. Sends events about new orders, orders status change, swap state changes between two users, etc.

Only one argument available - config:

{
  EXPERIMENTAL: {
    pubsub: true,
  },
  config: {
    Addresses: {
      Swarm: [
        '/dns4/ws-star.discovery.libp2p.io/tcp/443/wss/p2p-websocket-star',
      ],
    },
  },
}

Public props

Prop name Description
peer Current user peer

Public methods

Method name Description
on(eventName, handler)
off(eventName, handler)
once(eventName, handler) Call handler once and unsubscribe
sendMessage([
  {
    event: 'new order',
    data: {
      order,
    },
  },
  ...
])
Accepts array of messages

[swap.orders] SwapApp.services.orders

Provides the workflow with orders - create, store, update, remove orders.

Public methods

Method Description
create({
  buyCurrency: 'PUFFS',
  sellCurrency: 'BTC',
  buyAmount: 10,
  sellAmount: 1,
  exchangeRate: 0.1,
})
Order entity allows to contain only certain props: buyCurrency, sellCurrency, buyAmount, sellAmount, exchangeRate
remove(orderId)
getMyOrders() Get all my orders
getPeerOrders(peer) Get all user's orders by his peer. If user offline returns [ ]
on(eventName, handler) Subscribe for event
off(eventName, handler) Unsubscribe

Events

Event name Description
new orders Other user becomes online and send all his orders to other peers
new order Other user creates an order
remove order Other user removes an order

[swap.swaps]

This package contains set of classes which provide functionality for swap operations: deposit funds, check balance, withdraw, refund, abort swap, etc. Each file (class) written for specific blockchain (PuffsSwap, BtcSwap) / coin (PuffsTokenSwap). These classes used inside Swap process by swap.flows, developer needs only to pass necessary class to SwapApp setup config:

swapApp.setup({
  ...
  swaps: [
    new PuffsSwap({
      address: '0xdbC2395f753968a93465487022B0e5D8730633Ec',
      abi: [{"constant":false,"inputs":[{"name":"_secret","type":"bytes32"},{"name":"_ownerAddress","type":"address"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_participantAddress","type":"address"}],"name":"getSecret","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_ratingContractAddress","type":"address"}],"name":"setReputationAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"participantSigns","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_ownerAddress","type":"address"}],"name":"abort","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"swaps","outputs":[{"name":"secret","type":"bytes32"},{"name":"secretHash","type":"bytes20"},{"name":"createdAt","type":"uint256"},{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_secretHash","type":"bytes20"},{"name":"_participantAddress","type":"address"}],"name":"createSwap","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_ownerAddress","type":"address"}],"name":"checkSign","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_participantAddress","type":"address"}],"name":"close","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ratingContractAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_participantAddress","type":"address"}],"name":"sign","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_ownerAddress","type":"address"}],"name":"getBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_participantAddress","type":"address"}],"name":"refund","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"Sign","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"createdAt","type":"uint256"}],"name":"CreateSwap","type":"event"},{"anonymous":false,"inputs":[],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[],"name":"Close","type":"event"},{"anonymous":false,"inputs":[],"name":"Refund","type":"event"},{"anonymous":false,"inputs":[],"name":"Abort","type":"event"}],
      fetchBalance: (address) => puffscoinInstance.fetchBalance(address),
    }),
    new BtcSwap({
      fetchBalance: (address) => bitcoinInstance.fetchBalance(address),
      fetchUnspents: (scriptAddress) => bitcoinInstance.fetchUnspents(scriptAddress),
      broadcastTx: (txRaw) => bitcoinInstance.broadcastTx(txRaw),
    }),
    ...
  ],
  ...
})

Each *Swap should extends swap.app/SwapInterface:

class SwapInterface {

  constructor() {
    // service name, within it will be stored in SwapApp.swaps
    this._swapName = null
  }

  _initSwap() {
    // init service on SwapApp mounting
  }
}
  • this._swapName required by SwapApp setup process, within it will be stored in SwapApp.swaps[_swapName]
  • _initSwap() will be called when swap be mounted

BtcSwap

Public methods
/**
 *
 * @param {object} data
 * @param {string} data.secretHash
 * @param {string} data.ownerPublicKey
 * @param {string} data.recipientPublicKey
 * @param {number} data.lockTime
 * @returns {{scriptAddress: *, script: (*|{ignored})}}
 */
createScript(data)
/**
 *
 * @param {object} data
 * @param {string} data.recipientPublicKey
 * @param {number} data.lockTime
 * @param {object} expected
 * @param {number} expected.value
 * @param {number} expected.lockTime
 * @param {string} expected.recipientPublicKey
 * @returns {Promise.<string>}
 */
checkScript(data, expected)
/**
 *
 * @param {object} data
 * @param {object} data.scriptValues
 * @param {BigNumber} data.amount
 * @param {function} handleTransactionHash
 * @returns {Promise}
 */
fundScript(data, handleTransactionHash)
/**
 *
 * @param {object|string} data - scriptValues or wallet address
 * @returns {Promise.<void>}
 */
getBalance(data)
/**
 *
 * @param {object} data
 * @param {object} data.scriptValues
 * @param {string} data.secret
 * @param {boolean} isRefund
 * @returns {Promise}
 */
getWithdrawRawTransaction(data, isRefund)
/**
 *
 * @param {object} data
 * @param {object} data.scriptValues
 * @param {string} data.secret
 * @param {boolean} isRefund
 * @returns {Promise}
 */
getWithdrawHexTransaction(data, isRefund)
/**
 *
 * @param {object} data
 * @param {object} data.scriptValues
 * @param {string} data.secret
 * @returns {Promise}
 */
getRefundRawTransaction(data)
/**
 *
 * @param {object} data
 * @param {object} data.scriptValues
 * @param {string} data.secret
 * @returns {Promise}
 */
getRefundHexTransaction(data)
/**
 *
 * @param {object} data
 * @param {object} data.scriptValues
 * @param {string} data.secret
 * @param {function} handleTransactionHash
 * @param {boolean} isRefund
 * @returns {Promise}
 */
withdraw(data, handleTransactionHash, isRefund)
/**
 *
 * @param {object} data
 * @param {object} data.scriptValues
 * @param {string} data.secret
 * @param {function} handleTransactionHash
 * @returns {Promise}
 */
refund(data, handleTransactionHash)

PuffsSwap

Public methods
/**
 *
 * @param {object} data
 * @param {string} data.participantAddress
 * @param {function} handleTransactionHash
 * @returns {Promise}
 */
sign(data, handleTransactionHash)
/**
 *
 * @param {object} data
 * @param {string} data.secretHash
 * @param {string} data.participantAddress
 * @param {number} data.amount
 * @param {function} handleTransactionHash
 * @returns {Promise}
 */
create(data, handleTransactionHash)
/**
 *
 * @param {object} data
 * @param {string} data.ownerAddress
 * @returns {Promise}
 */
getBalance(data)
/**
 *
 * @param {object} data
 * @param {string} data.ownerAddress
 * @param {BigNumber} data.expectedValue
 * @returns {Promise.<string>}
 */
checkBalance(data)
/**
 *
 * @param {object} data
 * @param {string} data.secret
 * @param {string} data.ownerAddress
 * @param {function} handleTransactionHash
 * @returns {Promise}
 */
withdraw(data, handleTransactionHash)
/**
 *
 * @param {object} data
 * @param {string} data.participantAddress
 * @param {function} handleTransactionHash
 * @returns {Promise}
 */
refund(data, handleTransactionHash)
/**
 *
 * @param {object} data
 * @param {string} data.participantAddress
 * @returns {Promise}
 */
getSecret(data)
/**
 *
 * @param {object} data
 * @param {string} data.participantAddress
 * @param handleTransactionHash
 * @returns {Promise}
 */
close(data, handleTransactionHash)

PuffsTokenSwap

Public methods
/**
 *
 * @param {object} data
 * @param {string} data.participantAddress
 * @param {function} handleTransactionHash
 * @returns {Promise}
 */
sign(data, handleTransactionHash)
/**
 *
 * @param {object} data
 * @param {BigNumber} data.amount
 * @param {function} handleTransactionHash
 * @returns {Promise}
 */
approve(data, handleTransactionHash)
/**
 *
 * @param {object} data
 * @param {string} data.owner
 * @param {string} data.spender
 * @returns {Promise}
 */
checkAllowance(data)
/**
 *
 * @param {object} data
 * @param {string} data.secretHash
 * @param {string} data.participantAddress
 * @param {BigNumber} data.amount
 * @param {function} handleTransactionHash
 * @returns {Promise}
 */
create(data, handleTransactionHash)
/**
 *
 * @param {object} data
 * @param {string} data.ownerAddress
 * @returns {Promise}
 */
getBalance(data)
/**
 *
 * @param {object} data
 * @param {string} data.ownerAddress
 * @param {BigNumber} data.expectedValue
 * @returns {Promise.<string>}
 */
checkBalance(data)
/**
 *
 * @param {object} data
 * @param {string} data.secret
 * @param {string} data.ownerAddress
 * @param {function} handleTransactionHash
 * @returns {Promise}
 */
withdraw(data, handleTransactionHash)
/**
 *
 * @param {object} data
 * @param {string} data.participantAddress
 * @param {function} handleTransactionHash
 * @returns {Promise}
 */
refund(data, handleTransactionHash)
/**
 *
 * @param {object} data
 * @param {string} data.participantAddress
 * @returns {Promise}
 */
getSecret(data)
/**
 *
 * @param {object} data
 * @param {string} data.participantAddress
 * @param handleTransactionHash
 * @returns {Promise}
 */
close(data, handleTransactionHash)

[swap.flows]

This package contains set of classes which describe how swaps will be processed step by step.

BTC2PUFFS

Requires: BtcSwap, PuffsSwap

PUFFS2BTC

Requires: BtcSwap, PuffsSwap

BTC2PUFFSTOKEN

* Note this is class factory

Requires: BtcSwap, PuffsTokenSwap

PUFFSTOKEN2BTC

* Note this is class factory

Requires: BtcSwap, PuffsTokenSwap


Examples

React

cd ./examples/react
npm i
npm start

Vanilla

Still not working

Your app

There are couple of ways to use swap.core packages in your app:

  1. Copy whole src/ to your own app folder and use relative paths... a lot of pain

  2. Use app-module-path-node to resolve module paths

  3. Webpack - to resolve swap packages use aliases

resolve: {
  alias: {
    'swap.app': '<PATH_TO_SWAP.CORE>/src/swap.app',
    'swap.auth': '<PATH_TO_SWAP.CORE>/src/swap.auth',
    ...
  }
}

How swap works step by step (DEPRECATED)

Alice persist Alice BTC -> PUFFS Bob PUFFS -> BTC Bob persist
PuffsContract.checkSign() 1) Wait for sign 1) Sign
2) Create secret hash 2) Wait for BTC script BtcSwap.checkBalance()
3) Check balance (if not enough wait until user fill balance on this step)
4) Create BTC script
5) Fund BTC script
PuffsSwap.checkBalance() 6) Wait for PUFFS contract 3) Verify BTC script
4) Check balance (if not enough wait until user fill balance on this step)
5) Create PUFFS contract
7) Withdraw from PUFFS contract 6) Wait for withdraw from PUFFS contract PuffsSwap.getSecret()
7) Withdraw from BTC script

About

Decentralized JS library for secure cross-chain swaps. USDT<>BTC<>PUFFS<>PUFFS tokens (ERC20) via ipfs.js

https://puffsswap.leafycauldronapothecary.com


Languages

Language:JavaScript 100.0%