Changing A Wallet Policy Tutorial

What is a Policy

Each wallet has an associated policy that dictates the private/public keys which are allowed to spend from it. This key is called the Instruction Key and is kept in the secure enclave of the iPhone device that you onboarded with. However API users can change the Instruction Key so they sign transactions without the phone.

This tutorial is for users who:

  • Wish to register their new Instruction Key (i.e. want to remove the iOS device from the signing process and manage their Instruction Key).
  • Already manage their own Instruction Key and wish to rotate it.

For iPhone users changing phones then the recovery process is done via our app and the following tutorial is not relevant.

Brief Outline

Note: This process only needs to be done once for every wallet owned.

  1. Get a reference to your private and public key
    1. For testing you can create a key pair locally
    2. For Production you MUST use a secure key storage solution (e.g. AWS KMS)
  2. Create a new wallet policy for your wallet that includes your new Instruction Key
  3. Verify the response obtained from the creation of the new wallet policy is valid
    1. For testing purposes you can skip this step
    2. For Production we highly recommend you verify the data
  4. Sign the data
    1. If your signing solution requires the pre-image data then use the unverifiedDigestData.signData and use the SHA256 hashing algorithm
    2. If your signing solution can sign hash data then use the unverifiedDigestData.shaSignData
  5. Submit the public key and signature by calling the AddSignature mutation
  6. Repeat this for all wallets that need to be updated with the new Instruction Key

JavaScript Example

In this example you will need to call:

Sandbox users can comment out the verifyChangePolicyData for faster development but we highly recommend you implement it for Production

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import { ec as EC } from "elliptic";
import { ApiClient } from "../src/ts/_api-client";

// For demonstration purposes only. Do not hard code your key, store it somewhere safe (AWS KMS).
const privateKey = "57c3324ad96158abd517548d03285c79253e681b4fc80f530f5c1a195c6f7d50";
// Create your key pair from your private key which you need for signing
const keyPair = new EC("p256").keyFromPrivate(privateKey);

// For demonstration purposes only. Do not hard code your API key, store it somewhere safe (AWS KMS).
const userApiKey = "b3ef7694-3ab7-4115-9887-0544399fe620-test-api-key-prod";
const productionUrl = "https://tapi-production.trustology-prod.com/graphql";
// API reflects the postman query written in JavaScript
const apiClient = new ApiClient(userApiKey, productionUrl);

// The walletId retrieved from get-wallets
const walletId = "my-wallet-guid"

// Get the public Key
const newPublicKey = keyPair.getPublic("hex");

// Call the changePolicyRequest function with the newPublicKey
(() => async {
const requestId = await changePolicyRequest(walletId, newPublicKey);
})();


/**
* Updates the Instruction Key of a wallet policy with the new public key given
* @param walletId - The walletId retrieved from the User Wallets query that you wish to update
* @param newPublicKey - the new public key which you wish to use for the wallet
*/
async function changePolicyRequest(walletId, newPublicKey) {
// call createChangePolicyRequest mutation with the new public key to get the policyTemplate
const result = await apiClient.createChangePolicyRequest(walletId, newPublicKey);

// Production users are highly recommended to verify the data returned by TrustVault. Sandbox users can use the unverifiedDigestData.shaSignData field
verifyChangePolicyData(result, newPublicKey);
const unverifiedDigest = result.unverifiedDigestData.shaSignData;

// using you private key pair, sign the digest.
const { r, s } = keyPair.sign(unverifiedDigest);
// convert the r, s bytes signature to hex format
const hexSignature = r.toString("hex", 64) + s.toString("hex", 64);
// construct the sign request payload for the add signature mutation
const signRequest = {
publicKeySignaturePairs: [
{
publicKey: keyPair.getPublic("hex"), // should be in hex string format
signature: hexSignature, // should be in hex string format
},
],
};

// submit the addSignature payload and receive back the requestId of your change policy request
const requestId = await apiClient.addSignature({
requestId: result.requestId,
signRequests: [signRequest],
};);
console.log(`successfully submitted recovery request with id ${requestId}`);

return requestId;
}