NAV
typescript graphql shell

Introduction

Welcome to Tokensoft's developer documentation. This guide illustrates how our partners can interact with Tokensoft services programmatically in the following use cases:

Note that certain features are restricted: please contact us for more instructions on accessing this API.

Authentication

Almost all API endpoints require API users to authenticate. Each request must include:

The Tokensoft SDK takes care of this logic, and we encourage you to use it.

This is an example request which provides the access-key, access-sign, and access-timestamp headers.

const fetch = require('node-fetch')
const crypto = require('crypto')

const url = 'https://platform.stagetokensoft.com/graphql'
// access and secret keys obtained from your admin dashboard
const accessKey = 'your access key'
const secretKey = 'your secret key'

// create a signature for the request body
const createSignature = (body, timestamp, secretKey) => {
  const text = timestamp + body
  const hmac = crypto.createHmac('sha256', secretKey)
  hmac.update(text)
  return hmac.digest('hex')
}

const getServerTime = async () => {
  const request = {
    query: '{ time }'
  }
  const body = JSON.stringify(request)
  const options = {
    headers: {
      'Content-Type': 'application/json',
    },
    method: 'post',
    body
  }

  const res = await fetch(url, options)
  const { data } = await res.json()
  return data.time
}

const run = async () => {
  const timestamp = await getServerTime()
  const body = JSON.stringify({ query: '{ currentUser { id email } }' })
  const signature = createSignature(body, String(timestamp), secretKey)

  const options = {
    // include signature and timestamp to request headers
    headers: {
      'access-key': accessKey,
      'access-sign': signature,
      'access-timestamp': timestamp,
      'Content-Type': 'application/json',
    },
    method: 'post',
    body
  }

  try {
    const res = await fetch(url, options)
    console.log('res', res)
    const { data } = await res.json()
    console.log('data', data)
  } catch (e) {
    console.log('e', e)
  }
}

run()

SDK

Tokensoft also has an SDK (https://www.npmjs.com/package/tokensoft-sdk) which simplifies interactions with the API.

# installation
npm install tokensoft-sdk
import TokensoftSDK from 'tokensoft-sdk'

const issuerEndpoint = 'https://app.arcalabs.com'

const sdk = new TokensoftSDK(issuerEndpoint, process.env.KEY_ID, process.env.SECRET_KEY)

Sandbox Environment

API integrations should be tested against a Tokensoft sandbox environment before being used in any production environment. Tokensoft also supports the GraphQL Playground tool for rapid API testing.

Platform

The Tokensoft Platform supports token issuers managing digital securities and investors purchasing the securities.

Tokensoft Investment Account (TIA)

TIA supports investors holding and using digital securities.

Use Cases

User Whitelisting

Trading venues,such as an ATS, face two challenges when supporting digital asset securities.

First, they have their own AML/KYC compliance programs for their users, so investors buying or selling ERC-1404 digital asset securities might need to submit duplicate AML/KYC information to both the issuer and the ATS, creating a redundant and unnecessarily slow compliance process.

Second, they need to ensure that any on-chain compliance restrictions do not cause trade settlement to fail unexpectedly, so they might need to monitor every security token contract.

Tokensoft’s API solves these problems through the following:

ATS partners can use these API endpoints to request on-chain whitelisting of an investor so that they are certain secondary transactions will settle as-expected.

The API collects kyc information about the user as detailed in the example

mutation {
  whitelistUser(email:"[email protected]", ethAddress:"0x00192fb10df ... 3cd1bf599e8", kyc: {
    firstName:"john",
    lastName:"doe",
    address: {
      streetAddress:"123 abc street",
      city:"San Francisco",
      state:"CA",
      zip:"94000",
      country:"US"
    }
  })
}
// using the tokensoft sdk
const transactionHash = await sdk.authorizeUser(
  '[email protected]',
  '0x00192fb10df ... 3cd1bf599e8',
  {
    firstName:"john",
    lastName:"doe",
    address: {
      streetAddress:"123 abc street",
      city:"San Francisco",
      state:"CA",
      zip:"94000",
      country:"US"
    }
  }
)

The mutation returns the hash of the add-to-whitelist transaction.

If an error occured, the mutation returns null. (Note: in a future relase, an error message and code will be provided)

Token Pricing

Token price feed providers can query the current or historical price of a token supported by Tokensoft.

// Query current price
query getLatestPrice {
  getLatestPrice(symbol: "TSFT")
}

// Query historical prices.
query getTimestampPrice {
  getTimestampPrice(symbol: "usdt", IsoTimestamp:"2020-06-20T03:54:32") {
    arcaPrice
    usdcPrice
  }
}
curl -i -H 'Content-Type: application/json' -X POST -d '{"query": "query {getLatestSupply(product: \"Wrapped ZEC (WZEC)\") {totalSupply, circulatingSupply, dateTime}}"}' https://portal.wrapped.com/graphql

Token Supply

The supply of a Token can be queried with the getSupply and getLatestSupply endpoints. The total supply is the total amount of tokens minted. The circulating supply is the total supply excluding tokens held in reserve accounts.

query {
  getLatestSupply(product: "ARCA") {
    totalSupply
    circulatingSupply
  }
}

query {
  getSupply(product:"ARCA", start: "2019-01-01T00:00:00.000Z", end: "2021-10-21T17:51:44.265Z") {
    totalSupply,
    circulatingSupply,
    dateTime
  }
}

Derived Wallet Address

A TIA specific URI that allows a derived wallet address to be determined before the wallet is deployed. This is good for pre-calculating the destination where funds will end up for token distributions.

The calling account must be pre-authorized to access this API.

query getDerivedWalletAddress(
  $id: ID!
){
  getDerivedWalletAddress(
    id: $id
  )
}

Buy/Sell Tokens

This mutation is a TIA Specific API Endpoint that allows users to create a buy or sell order. (Note: In order to create a sell order you must have funds in your account.)

All input variables are required except "tradeType" which will default to "BROKER_DEALER"

orderType options:
"BUY_ORDER_TYPE"
"SELL_ORDER_TYPE"

tradeType options:
"BROKER_DEALER"
"DVP_BROKER_DEALER"
mutation createOrder(
  input: {
    productId: "5e4598hy531ac5a18df7yg8c97"
    orderType: "BUY_ORDER_TYPE"
    price: 3
    quantity: "300"
    tradeType: "BROKER_DEALER"
  }
) {
  id
  referenceNumber
  tradeType
  counterpartyProduct {
    id
    tokenLabel
    decimals
    tokenAddress
  }
  documents {
    id
    filename
    downloadUrl
    uploadedAt
  }
  onchainTransactions
  orderType
  price
  productWalletState {
    id
  }
  quantity
  amount
  amountString
  state
  createdAt
  updatedAt
}

Get Token Balances

This query is a TIA Specific API Endpoint that will return the balance for each asset associated to a user if a wallet id is provided. (Note: "walletId" is the only input variable and is required).

The query also returns a product which makes it possible to query more details about products that have a balance (Ex: tokenName).

(Note: "ProductWalletState" represents the current relationship between a specific wallet and a product.)

query GetProductWalletStates {
  getProductWalletStates(
    walletId: "5e4598hy531ac5a18df7yg8c97"
  ) {
    id
    balance
    product {
      id
      tokenName
      ...
    }
  }
}

KYC Check Status

This is a Platform Specific API Endpoint to allow querying the status of a user's KYC check.

The calling account must be authorized to view KYC status on the user being requested.

Results are shown in a breakdown and subBreakdowns arrays that details which specific checks passed or failed.

query{
 getKycCheck(id: "CHECK_ID"){
  id,
  reports{
    id
    createdAt,
    breakdown{
      name
      result
      properties {
        key
        value
      }
      subBreakDowns{
        name
        result
        properties{
          key
          value
        }
      }
    }
  }
}
}

result:

{
  "data": {
    "getKycCheck": {
      "id": "ids321",
      "reports": [
        {
          "breakdown": [
            {
              "name": "date_of_birth",
              "properties": [],
              "result": "unidentified",
              "subBreakDowns": [
                {
                  "name": "date_of_birth_matched",
                  "properties": [],
                  "result": null
                }
              ]
            },
            {
              "name": "address",
              "properties": [],
              "result": "clear",
              "subBreakDowns": [
                {
                  "name": "address_matched",
                  "properties": [
                    {
                      "key": "sources",
                      "value": "Credit Agencies"
                    }
                  ],
                  "result": "clear"
                }
              ]
            }
          ],
          "createdAt": "2019-11-07T18:03:40Z",
          "id": "ids123"
        }
      ]
    }
  }
}