Who is this tutorial for:
- API users that DO NOT use their iPhone as the Instruction Key.
 - API users that need to implement the functionality in programming languages other than JavaScript
 - API users that DO NOT want to use our JavaScript SDK.
 
Brief Outline
- Get your subWallet id from the User Wallets Details Query
 - Create a bitcoin transaction via the Create BTC Transaction Mutation
 - 
Verify the transaction and that it was sent by TrustVault
- For testing purposes (sandbox environment) you can skip this step
 - For Production we highly recommend you verify the data
 
 - 
Sign each transaction input
- 
If your signing solution requires the pre-image data then use the 
input.unverifiedDigestData.signDataand use the SHA256 hashing algorithm - 
If your signing solution can sign hash data then use the 
input.unverifiedDigestData.shaSignData 
 - 
If your signing solution requires the pre-image data then use the 
 - Submit the signatures in the same order as the inputs via the Add Signature Mutation
 - Poll the status of the transaction to confirm it was sent to the network using the Get Request Item Query
 
JavaScript Example
Below is a brief example for creating, signing and submitting a BTC transaction. Sandbox users can comment out the verifyBitcoinTransaction for fast implementation but MUST implement it for Production. The code for verifyBitcoinTransaction will be made available soon.
import { ApiClient } from "./api-client";
import * as AWS from "aws-sdk";
// Create instance of KMS for key signing
const kms = new AWS.KMS({ apiVersion: "2014-11-01", region: "eu-west-1" });
// Get the public Key (This will need to be your own custom code to pull the PublicKey from the AWS KMS publicKey which is a DER-encoded X.509 public key, also known as SubjectPublicKeyInfo (SPKI), 
// Sample code: https://github.com/Trustology/trustvault-nodejs-sdk/blob/master/src/ts/sign-examples/aws-kms.ts
// https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html
const newPublicKey = getUncompressedPublicKeyInHex(await this.kms.getPublicKey({KeyId: "my-key"}).promise())
// For demonstration purposes only. Do not hard code your API key, store it somewhere safe.
const userApiKey = "test-api-key";
// Production
const prodUrl = "https://tapi-production.trustology-prod.com/graphql";
// API reflects the postman query written in JavaScript
const apiClient = new ApiClient(userApiKey, prodUrl);
/**
 * Sends a bitcoin transaction with the given parameters
 * 1. Creates the bitcoin transaction from the fromSubWalletId with the given parameters
 * 2. Validates the returned transaction
 * 3. Signs and submits the key signature pairs
 * 2. Polls the request status to see if it has been successfully submitted to the network
 *
 * @param {string} fromSubWalletId - the unique identifier retrieved from the User Wallets Query where the bitcoin transaction will be sent from
 * @param {string} toAddress - the address where the bitcoin transaction that will be sent to (we support P2SH, P2PKH, P2WPKH, P2SH-P2WPKH address types)
 * @see https://bitcoin.stackexchange.com/a/64852 for an explanation of different bitcoin addresses
 * @param {string} amount - the amount to send in satoshi (integer string)
 * @param {string} speed - "FAST" | "MEDIUM" | "SLOW"
 * @returns {string} requestId - the unique identifier of the created bitcoin transaction request needed for transaction tracking
 */
async function sendBitcoin(fromSubWalletId, toAddress, amount, speed) {
  // call createBitcoinTransaction mutation with the parameters to get a well formed bitcoin transaction
  const result = await apiClient.createBitcoinTransaction(fromSubWalletId, toAddress, amount, speed);
  if (!result.signData || !result.requestId) {
    console.error(`Failed to create bitcoin transaction ${JSON.stringify(result)}`);
    throw new Error("Failed to create bitcoin transaction");
  }
  // IMPORTANT: PRODUCTION users are highly recommended to verify the bitcoin transaction (input/outputs are correct and were sent by TrustVault)
  verifyBitcoinTransaction(result.signData, fromSubWalletId, toAddress, amount);
  // IMPORTANT: PRODUCTION users are highly recommended to NOT use the unverifiedDigestData but instead recreate the digests
  const unverifiedSignedDataDigests: string[] = result.signData.transaction.inputs.map(
    // If your signing solution requires the pre-image data then use the `input.unverifiedDigestData.signData`.
    (input) => input.unverifiedDigestData.shaSignData,
  );
  // Sign each signRequest with your key pair
  const signRequests = unverifiedSignedDataDigests.map((signedDigest) => {
    // using you private key pair secured in KMS, sign the digest.
    // custom function. Use the sample code "sign" function and pull out the r,s values: https://github.com/Trustology/trustvault-nodejs-sdk/blob/master/src/ts/sign-examples/aws-kms.ts
    const { r, s } = signAndReturnRandSSignature(kms, signedDigest);
    // convert the r, s bytes signature to hex format
    const hexSignature = r.toString("hex", 64) + s.toString("hex", 64);
    return {
      publicKeySignaturePairs: [
        {
          publicKey: newPublicKey, // 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 bitcoin transaction request
  const requestId = await apiClient.addSignature({
    requestId: result.requestId,
    signRequests,
  });
  // Check that your transaction was successfully submitted to the network
  const expectedStatus = "SUBMITTED";
  const status = await pollRequestStatus(requestId, expectedStatus);
  console.info(`request (${requestId}) - status: ${status}`);
  return requestId;
}