Skip to main content

Send Payment/Token From A Wallet

POST /v1/trovo-api/users/payment

Protocol To Send Payment/Token From A Wallet

Sending only happens from within wallets that are within the enterprise's scope. Attempts to send a token from a different wallet will fail. Payment and transaction bound interactions typically happen in two phases. Initial call with base parameters which then pre-fills the other parameter. SPECIFY THE SENDER/SOURCE WALLET using the Headers.

NOTE: When using a sub-wallet with shared access, ENSURE TO GRANT THE owner an INITIATOR PRIVILEGE on the subwallet.

The returned object contains the submitted information as well as all needed information that will help complete signing of transactions. When the transaction is signed, then append it to the right key in the returned object and then submit the entire object back to the API. Once the signatures are verified and transaction integrity is determined, then it is submitted to the blockchain for execution or saved for approvals in case of shared access transactions. The JSON response object is the same as the JSON body object. But for convenience and clarity, we will specify only the basic JSON body required parameters for the initial request. This means that other fields can be left empty.

Destination: is the public key or trovo app username of the wallet that will receive the sent token. Required.

Memo: this is max of 28bytes (character) which can be used to denote the transaction. This is Optional.

AssetIssuer: this is the 56 character public key of the issuer of the asset/token. Required.

AssetCode: Max of 12 alphanumeric characters that represents the code of the token to be sent.

Amount: this is the amount of token units to be sent to the destination wallet.

Transaction: this is the composed base64Txn XDR transaction string for the operation that is returned as a response after the initial call with the initial JSON BODY. This transaction would be signed with the proper stellar SDK. The signature obtained from the singing progress is then appended to the TransactionSignature key. Mandatory return with the second call to the API. The value must be used exactly as it was returned.

TransactionSignature: should hold the resulting string from signing of the Transaction that was retrieved from the initial call to the api. SAMPLE CODE

TransactionID: is returned after the second call to the API, if it is successful and blockchain execution occurred, then it will return a TRANSACTION HASH for the execution on the blockchain. If it is a shared access operation, then it will return PENDING_AUTH as a string, which indicates the signers should approve the transaction on their wallets.

NetworkPassPhrase: is returned after the initial call. This is the network passphrase that would be used during signing of the transaction returned on the initial call to API. The string should be used exactly as it is.

DestinationFirstName/DestinationLastName/DestinationThumbnail: depicts the corresponding data of the destination specified.

SignatureRequired: value of 1 indicates that the transaction signature is required and the client must sign the attached transaction and append the transaction signature in the right key. Value 0 means the client does not need to sign the transaction.

Commit: This is for all shared access operations that are being submitted by an initiator. When an initiator submits a request request, it should initially be sent with Commit = 0, and when you have confirmed the information returned, you can alter the commit = 1 and send back the objects. This will commit the request and notify all stakeholders that the operation concerns. If you are doing operations from a wallet that is not a shared access wallet, this should be ignored.

Messages: This is a list of messages and warnings from the api service that concerns your transaction you submitted. Usually it is an array of messages to be shown to the user or ignored.

Specific Headers For Sending Payment: Must Be Available

  • X-TW-PUBLIC-KEY must be the public key of the wallet that you are sending the token from.

  • X-TW-SIGNER must be the signer of the sender wallet. Usually it is the same as the primary wallet public key. Primary wallet is the wallet that is default on the profile.

Json Body/Response:

{
Destination string `json:"destination"`
Memo string `json:"memo"`
AssetIssuer string `json:"assetIssuer"`
AssetCode string `json:"assetCode"`
Amount string `json:"amount"`
Transaction string `json:"transaction"`
TransactionSignature string `json:"transactionSignature"`
TransactionID string `json:"transactionId"`
NetworkPassPhrase string `json:"networkPassPhrase"`
DestinationFirstName string `json:"destinationFirstName"`
DestinationLastName string `json:"destinationLastName"`
DestinationThumbnail string `json:"destinationThumbnail"`
DestinationVerified int `json:"destinationVerified"`
SignatureRequired int `json:"signatureRequired"`
Commit int `json:"commit"`
Fee string `json:"fee"`
FeeAmount string `json:"feeAmount"`
AmountToPay string `json:"amountToPay"`
Messages [ ]string `json:"messages"`
}

INITIAL CALL:

Destination, AssetIssuer, AssetCode, Amount

SECOND CALL must include: TransactionSignature

Sample Send Token Code

Sign Transaction Function

signSendTokenBase64Txn.js
import { Keypair, Transaction, Utils } from "stellar-sdk";

/**
* Sign a Stellar Transaction XDR (base64) with 1 secret key
* and return ONLY the base64-encoded signatures (not the signed envelope)
*
* @param {string} primarySecretKey
* @param {string} base64Txn
* @param {string} networkPassPhrase
* @returns {Promise<{primarySignature: string}>}
*/
export async function SignSendTokenBase64Txn(
primarySecretKey,
base64Txn,
networkPassPhrase
) {
try {
// ---- equivalent of keypair.ParseFull ----
const primaryKP = Keypair.fromSecret(primarySecretKey);

// ---- parse transaction from base64 XDR ----
const tx = new Transaction(base64Txn, networkPassPhrase);

// ---- calculate tx hash ----
const txHash = tx.hash(); // returns Buffer of the transaction hash

const primarySignature = primaryKP.sign(txHash).toString("base64");

return {
primarySignature,
};
} catch (err) {
throw err;
}
}

Send Token Function

sendToken.js
import axios from "axios";
import { Keypair, Networks, Transaction } from "stellar-sdk";

async function sendToken() {
try {
// === 1️⃣ CONFIGURATION ===
const API_URL = BASE_URL + "/v1/trovo-api/users/payment";

// Issuer (the account that created the asset)
const assetIssuer = "PUBLIC KEY OF ISSUER";

// Destination (the account that will receive the token)
const destination = "PUBLIC KEY OR WALLET ALIAS TO RECEIVE THE TOKEN";

// Asset details
const assetCode = "RDH";
const amount = "200000000";
const memo = "send RDH";

// === 2️⃣ INITIAL REQUEST (Create unsigned transaction) ===
const sendRequestBody = {
assetCode,
assetIssuer,
destination,
amount,
memo,
};

console.log("🔹 Sending initial payment request...");
const { data: unsignedTxResponse } = await axios.post(
API_URL,
sendRequestBody
);

// The response should contain: Transaction (XDR) and NetworkPassPhrase
const { transaction: base64Txn, networkPassPhrase } = unsignedTxResponse;

if (!base64Txn || !networkPassPhrase) {
throw new Error(
"Invalid response — missing transaction or networkPassPhrase"
);
}

console.log("✅ Received unsigned transaction from server.");

// === 3️⃣ SIGN THE TRANSACTION ===
const primaryKeypair = Keypair.fromSecret(USER_PRIMARY_SECRET);
const result = await SignSendTokenBase64Txn(
primaryKeypair.secret(),
base64Txn,
networkPassPhrase
);

// === 4️⃣ SECOND CALL — Send back signed transaction ===
const signedBody = {
...unsignedTxResponse,
transactionSignature: result.primarySignature,
commit: 0,
};

console.log("🔹 Sending signed transaction back for payment commit...");
const { data: finalResponse } = await axios.post(API_URL, signedBody);

// === 5️⃣ SUCCESS RESPONSE ===
console.log("✅ Token send completed successfully!");
console.log("Transaction ID:", finalResponse.transactionId);
console.log("Full response:", finalResponse);
} catch (error) {
console.error(
"❌ Error sending token:",
error.response?.data || error.message
);
}
}

// Run the function
sendToken();

NOTE: If sender wallet is a shared access wallet with approvers, please ensure to set commit = 1 so as to commit the transaction for approval.