Tutorials

The trust-api is a GraphQL API so you’ll need to use a GraphQL client.

A GraphQL API is easy to work with as it allows:

  1. Self discovery of the API endpoints
  2. Easier versioning of the API
  3. Allows clients to request whatever data they want in (usually) a single call

There are many GraphQL clients available but Postman may be the easier to work with for testing purposes.

You can still use any HTTP client to send the queries as fundamentally GraphQL queries can be sent via HTTP POST and the responses parsed as valid JSON.

The tutorials are designed to help you get started with the basics of the API and assume you have a client that can take a query and variables.

Tutorial 1 - Getting Session Tokens

The trust-api authentication works through a Partial PIN process. This is simply where a users six digit PIN is validated by asking for 2 digits of that PIN. Since you don’t know which digits will be asked for, this is a two stage process.

  1. Request the PIN digits, called a PinChallenge
  2. Obtain the answers from your user and submit the response

Requesting a PinChallenge

To request a PinChallenge, simply issue the following query.

1
2
3
4
5
6
7
query($email: String!) {
getPartialPinChallenge(email: $email) {
sessionToken
firstPinDigitPosition
secondPinDigitPosition
}
}

Variables:

1
2
3
{
"email":"my_users_email@mail.com"
}

This is issuing a query passing in the email of your user and requesting the sessionToken, firstPinDigitPosition and secondPinDigitPosition.

The response to a pinChallenge request will be

1
2
3
4
5
6
7
8
9
{
"data": {
"getPartialPinChallenge": {
"sessionToken": "rE7TqbEqEdt6sTC8jvqcL7Cjq70gkkjWoIw7dfaA...",
"firstPinDigitPosition": "1",
"secondPinDigitPosition": "4"
}
}
}

NB: The sessionToken has been reduced in size.

The sessionToken must be stored and passed back in a subsequent query.

You can see that the response has given us which digits of the PIN we need to return (through the XXXXPinDigitPosition fields ), in this case it’s asking for the first digit and the fourth.

Responding to a PinChallenge

Now, we need to respond to the PinChallenge, so let’s assume the user PIN is 842876.

We can ask our user for those digits requested and submit the following response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
query(
$email: String!
$firstPinDigit: String!
$secondPinDigit: String!
$sessionToken: String!
) {
getAuthenticationTokens(
getAuthenticationTokensInput: {
email: $email
pinChallenge: {
sessionToken: $sessionToken
firstPinDigit: $firstPinDigit
secondPinDigit: $secondPinDigit
}
}
) {
authentication {
enc
iv
tag
}
}
}

Variables:

1
2
3
4
5
6
{
"email":"my_users_email@mail.com",
"firstPinDigit": "8",
"secondPinDigit":"8",
"sessionToken": "rE7TqbEqEdt6sTC8jvqcL7Cjq70gkkjWoIw7dfaA..."
}

This query, is simply passing back the email, sessionToken and the answers to the PinChallenge, and requesting the env, iv and tag tokens from the authentication type. If you fail to ask for the authentication type you’ll need to start the process again.

Should the PIN be correct, the result will look something like:

1
2
3
4
5
6
7
8
9
10
11
{
"data": {
"getAuthenticationTokens": {
"authentication": {
"enc": "5rfxa4N8aWYS5EWpZuq4pkFoVJx6OLt/...",
"iv": "sEYQMhhDf74XH2ZAmzNtfA==",
"tag": "1uaGcSlMvrQaW18qD/yUcw=="
}
}
}
}

NB: Tbe enc value has been reduced in size.

The enc, iv and tag tokens are now user sessions tokens which you should store and can be used in subsequent Query requests for the user wallet.

Troubleshooting

  • The sessionToken is valid for a short period of time, if it expires you’ll need to start the pinChallenge process again.
  • If you get the PIN wrong 3 times then the account is placed in PIN_RESET mode and the user will need to use the iOS app to reset their PIN.
  • For security reasons, you will NOT be notified if the email address is wrong so please check the email value carefully
  • An incorrect PIN will return an error such as below
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"data": {
"getAuthenticationTokens": {
"authentication": null
}
},
"errors": [
{
"path": ["getAuthenticationTokens"],
"data": null,
"errorType": "INVALID_PIN",
"errorInfo": null,
],
"message": "Invalid PIN, please try again"
}
]
}

Tutorial 2 - Creating a new Wallet

In order to create a new wallet there are a number of things that must be defined.

Most importantly you must provide a PolicyTemplate. This is broken into 2 main sections.

delegateSchedules

This simply defines the private keys (you reference them via their corresponding public keys) that must have signed a request for a it to be re-signed by the HSM with the correct keys. See the trust-sign API for further details on PolicyTemplates. These keys have spend access to the wallet

recovererSchedules

This simple defines the private keys (you reference them via their corresponding public keys) that must have signed a request to change an existing policy. The HSM will reject any changes not signed correctly.

Creating a Wallet Request

To create a wallet, submit a mutation request to the endpoint. This will create a request that will be delivered to the inbox of each public key owners device.

In order for a wallet to be created all the owners of the publicKeys specified in PolicyTemplate must sign the request. This is done through the iOS app. (API access to sign a wallet creation request will be added shortly)

NB: Each publicKey specified must have a corresponding TrustVault account registered with the publicKey that matches their devicePublicKey. Adding an incorrect publicKey will leave the request un-signable.

See this example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
mutation {
createWallet(
walletType: BITCOIN
walletName: "My Wallet"
walletPolicyTemplate: {
expiryTimestamp: 1577840400
delegateSchedules: [
[
{
keys: [
"044595b77dd9758d382268bac9f82f02640fab533b222e597f6c82e66d53d1faa01dc190ff17729c62763cffc7f7abc0e72d24243ff0773bfa8c70374a18b2180e"
"044595b77dd9758d382268bac9f82f02640fab533b222e597f6c82e66d53d1faa01dc190ff17729c62763cffc7f7abc0e72d24243ff0773bfa8c70374a18b2180e"
]
quorumCount: 1
}
{
keys: "044595b77dd9758d382268bac9f82f02640fab533b222e597f6c82e66d53d1faa01dc190ff17729c62763cffc7f7abc0e72d24243ff0773bfa8c70374a18b2180e"
quorumCount: 1
}
]
]
recovererSchedules: [
[
{
keys: [
"047c5e15091230f87a2e2e14d11dea53103aad06e4e271db282621ccc377fdf100c339557350839aa88a6809879c83e1c3f37fc6a42d5d6bbe10eeeca1e9fd81ac"
"04dd294cbbd831c977b47bae433a94d564b1dc446b2d7d305d263bd178c74b2dd41687b21db7f08c11b01bc090b1bdd80d94f7d3a54b4881e810e0a4153a187966"
"04aed00304191764c4ab31225881cd071af3f62d7f2480758e0a5f58ba8543e316553e3acc3c7c0d50f718c7f947da8908155808f72071168a514ffc869d9e0b50"
"04a875847170e3542b731f8cd21f24f61573cc5b3a6af60125eb42fe11d8816e20a6972f50b7938c76ffa5f633627e0988ae881849527684b59ae13181081ab802"
]
quorumCount: 2
}
]
]
}
) {
walletCreationId
walletCreationStatus
}
}

Looking at the details.

  • This creates a new wallet request for a wallet called “My Wallet”
  • The request will expire on unix time stamp 1577840400 which is 1st Jan 2020. The HSM will reject any action on this request after that date.
  • The PolicyTemplate defines 2 clauses
    • Clause 1 - a single key of the two defined can satisfy the policy
    • OR
    • Clause 2 - a single key of the single key defined can satisfy the policy
  • The recoversSchedule is the list of publicKeys needed to sign a request to change this policy in future
  • The walletCreationId and walletCreationStatus are returned. The walletCreationId can be used in the getWalletCreationStatus query to determine the status of the wallet creation request