Skip to content

Send a Payment

This guide sends a payment from one account to another: build a transaction, sign it, and submit it to the network. It is the core write flow every app needs.

Prerequisites

  • A funded source account and its keypair. If you do not have one, see Connect and Fund an Account.
  • The examples run on testnet, so they are free and safe to repeat.

Build the transaction

A payment is one operation inside a transaction. Load the source account for its current sequence number (the per-account counter the Digital World Network uses to order transactions), then build a transaction with a single Operation.payment. Here source is your funded keypair from Connect and Fund an Account, and destinationId is the recipient’s public key (a G... string):

import {
Gateway,
TransactionBuilder,
Operation,
Asset,
Networks,
BASE_FEE,
} from "@digitalworld/digital-world-sdk";
const gateway = new Gateway.Server("https://dex-testnet.digitalworld.global");
const account = await gateway.loadAccount(source.publicKey());
const tx = new TransactionBuilder(account, {
fee: BASE_FEE,
networkPassphrase: Networks.TESTNET,
})
.addOperation(
Operation.payment({
destination: destinationId,
asset: Asset.native(),
amount: "100",
}),
)
.setTimeout(30)
.build();

fee is the maximum per-operation fee you’re willing to pay, in SEEDS (BASE_FEE is 100; one NATIVE is ten million SEEDS). It’s a cap, not a fixed charge — the network only deducts what it actually needs at submission time, so a high fee (say, 5 NATIVE coins) makes the transaction more likely to be included when the network is busy without meaning all 5 NATIVE coins gets spent. amount is a string in whole units ("100" is 100 NATIVE coins). The destination must already exist on the network; to create and fund a brand-new account, use Operation.createAccount instead.

Sign and submit

A built transaction is unsigned. Sign it with the source account’s keypair, then submit it to Gateway:

tx.sign(source);
const result = await gateway.submitTransaction(tx);
result.hash; // the transaction hash
result.successful; // true when it was applied

If submission fails, Gateway returns the error in the rejected promise, so wrap the call in try/catch to inspect the failure. See Handle Errors for reading result codes and Gateway’s error responses.

Add a memo

Many services (exchanges, custodians) require a memo to route a payment. Add a Memo to the builder chain before .build():

import { Memo } from "@digitalworld/digital-world-sdk";
// ...the same builder as above, with one more line in the chain:
.addMemo(Memo.text("invoice-42"))

Send an issued asset

To send an issued asset instead of NATIVE coins, pass an Asset built from its code and the issuer account’s public key (issuerId). Everything else is the same:

const usd = new Asset("USD", issuerId);
Operation.payment({ destination: destinationId, asset: usd, amount: "100" });

The destination must already trust this asset, otherwise the payment fails. Setting up an issuer and trustlines is covered in Issue an Asset.

Put it together

The whole native-payment flow as one runnable script. It funds a throwaway source and destination with the faucet so the example runs end to end; in your app, source is your existing funded account and destination is any account that already exists:

import {
Keypair,
Gateway,
TransactionBuilder,
Operation,
Asset,
Memo,
Networks,
BASE_FEE,
} from "@digitalworld/digital-world-sdk";
const gateway = new Gateway.Server("https://dex-testnet.digitalworld.global");
async function main() {
const source = Keypair.random();
const destination = Keypair.random();
await Promise.all([
gateway.faucet(source.publicKey()).call(),
gateway.faucet(destination.publicKey()).call(),
]);
const account = await gateway.loadAccount(source.publicKey());
const tx = new TransactionBuilder(account, {
fee: BASE_FEE,
networkPassphrase: Networks.TESTNET,
})
.addOperation(
Operation.payment({
destination: destination.publicKey(),
asset: Asset.native(),
amount: "100",
}),
)
.addMemo(Memo.text("thanks!"))
.setTimeout(30)
.build();
tx.sign(source);
const result = await gateway.submitTransaction(tx);
console.log("Submitted:", result.hash, "successful:", result.successful);
}
main().catch(console.error);

You can now move value on the network. Next, learn to issue your own asset and set up trustlines.