Create an Ethereum Transaction

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

  1. Get the list of the available ethereum wallets its address, assets and their balance from the User Wallets Balances Query
  2. Create an ethereum transaction via the Create ETH/ERC20 Transaction Mutation
  3. Verify the transaction details is correct
  4. Create the digests (transactionDigest, signData, shaSignData) and verify this is the same as the fields in unverifiedDigestData (A tutorial how to do this will be made available soon)
    1. For testing purposes (sandbox environment) you can skip this step
    2. For Production we highly recommend to re-create the digests to verify
  5. Sign the appropriate digest according to your signing solution
    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 hashed data then use the unverifiedDigestData.shaSignData
  6. Submit the signature using the Add Signature Mutation
  7. 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 an Ethereum transaction. Sandbox users can comment out the verifyEthereumTransaction for fast implementation but MUST implement it for Production. The code for verifyEthereumTransaction will be made available soon.

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
63
64
65
66
67
68
69
70
71
const { ec: EC } = require("elliptic");
const { ApiClient } = require("./api-client");

// For demonstration purposes only. Do not hard code your key, store it somewhere safe.
const privateKey = "43c3324ad96158abd517548d03285c79253e681b4fc80f530f5c1a195a6f7e51";
// 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.
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 an ethereum transaction with the given parameters
* 1. Creates the ethereum transaction using the given parameters
* 2. Validates the returned ethereum transaction is what is expected
* 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} from - the address where the ethereum transaction will be sent from (use the User Wallets Query to get your list of ethereum wallet addresses)
* @param {string} to - the address where the ethereum transaction that will be sent to
* @param {string} value - the amount to send in wei (integer string)
* @param {string} assetSymbol - the symbol of the asset to be sent (ETH|RX|HOT|DAI2|BAT|DAI|EMR|VXV|MKR|OMG|PPT|REP|USDT|LINK|CBE)
* @param {string} speed - "FAST" | "MEDIUM" | "SLOW"
* @returns {string} requestId - the unique identifier of the created ethereum transaction request needed for transaction tracking
*/
async function sendEthereum(from, to, value, assetSymbol, speed) {
// call createEthereumTransaction mutation with the parameters to get a well formed ethereum transaction
const result = await apiClient.createEthereumTransaction(from, to, value, assetSymbol, speed);
if (!result.signData || !result.requestId) {
console.error(`Failed to create ethereum transaction ${JSON.stringify(result)}`);
throw new Error("Failed to create ethereum transaction");
}

// IMPORTANT: PRODUCTION users are highly recommended to verify the ethereum transaction is what is expected (toAddress, amount, assetSymbol and digests are correct)
verifyEthereumTransaction(result.signData, from, to, value, assetSymbol);

// IMPORTANT: PRODUCTION users are highly recommended to NOT use the unverifiedDigestData but instead recreate the digests
// If your signing solution requires the pre-image data then use the `result.signData.unverifiedDigestData.signData`.
const signDigest = result.signData.unverifiedDigestData.shaSignData;
// using you private key pair, sign the digest.
const { r, s } = keyPair.sign(signDigest);

// create the signRequests payload
const signRequests = [
{
publicKeySignaturePairs: [
{
publicKey: keyPair.getPublic("hex"), // should be in hex string format
signature: r.toString("hex", 64) + s.toString("hex", 64), // convert the r, s bytes signature to hex format
},
],
},
];

// submit the addSignature payload and receive back the requestId of your ethereum 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;
}