Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions docs/docs/api-reference/wallet/transfer/v1/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
sidebar_position: 1
---

# Wallet Transfer v1 Service

#### Skip The Details?
- 👉 Jump to **[Package Types](/docs/api-reference/wallet/transfer/v1/type)**
- 👉 Jump to **[Service Methods](/docs/api-reference/wallet/transfer/v1/service)**

{/*
Generated by protoc-gen-meshdoc the first time.
-> This file can be edited manually to add information about the Wallet Transfer Service.

THIS COMMENT AND EVERYTHING ABOVE IT IS AUTOGENERATED
*/}

## Overview

The **TransferService** manages asset transfers between accounts on the same ledger network. This service handles the full lifecycle of a transfer, from creation through on-chain execution, including fee calculation and state tracking.

Transfers are the primary mechanism for moving assets between accounts on the Mesh platform. Each transfer is:
- **Ledger-bound**: Both the source and destination accounts must be on the same ledger network
- **Fee-aware**: Transfer fees and VAT are automatically calculated
- **State-tracked**: Transfers progress through defined states (in progress, successful, failed)
- **Hierarchically scoped**: Owned by a group within your organizational hierarchy
- **Monitorable**: Real-time streaming updates as transfer state changes

## Common Workflows

### Basic Transfer

1. **Create Transfer** - Initiate a transfer specifying source address, destination address, and amount
2. **Monitor Transfer** - Subscribe to real-time state updates via streaming
3. **Verify Completion** - Confirm the transfer reached `TRANSFER_STATE_SUCCESSFUL`

### Transfer Auditing

1. **List Transfers** - Retrieve all transfers within your group hierarchy
2. **Search by Address** - Find all transfers involving a specific ledger address
3. **Get Transfer** - Retrieve details of a specific transfer by resource name

## Key Concepts

### Transfer States

Transfers progress through the following states:

| State | Description |
|-------|-------------|
| `TRANSFER_STATE_IN_PROGRESS` | Transfer has been submitted and is being processed on-chain |
| `TRANSFER_STATE_SUCCESSFUL` | Transfer completed successfully on the ledger |
| `TRANSFER_STATE_FAILED` | Transfer failed during on-chain execution |

### Ledger Addresses

The `from` and `to` fields use ledger-native addresses. Both addresses must be on the same ledger network. The address format determines which ledger the transfer executes on:

| Ledger | Address Format |
|--------|----------------|
| **Stellar** | Ed25519 public key |
| **Solana** | Ed25519 public key |

### Transfer Description

Transfers support an optional `description` field to record the reason for the transfer. When `include_in_ledger` is set to `true`, the description will be included in the on-chain ledger transaction, making it visible on the blockchain.

### Transfer Fees

Each transfer includes a `TransferFee` containing:
- **amount** - The calculated fee charged for the transfer
- **vat_rate** - The VAT rate applied to the fee calculation

Fees are calculated automatically by the system during transfer creation.

### Transfer Numbers

Each transfer receives a unique, monotonically increasing number that serves as a human-readable identifier. This number is system-generated and immutable.

## Authentication & Authorization

The TransferService uses role-based access control:

### Write Operations
Require `ROLE_WALLET_ADMIN` or `ROLE_WALLET_TRANSFER_ADMIN`:
- CreateTransfer

### Read Operations
Require any wallet role (`ADMIN` or `VIEWER` variants):
- GetTransfer
- ListTransfers
- SearchTransfersByAddress
- MonitorTransfer

All operations are scoped to your group's hierarchy - you can only access transfers owned by your group or its descendants.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package main

import (
"context"
"log"

typev1 "github.com/meshtrade/api/go/type/v1"
transferv1 "github.com/meshtrade/api/go/wallet/transfer/v1"
)

func main() {
ctx := context.Background()

// Default configuration is used and credentials come from MESH_API_CREDENTIALS
// environment variable or default discovery methods. Zero config required
// unless you want custom configuration.
service, err := transferv1.NewTransferService()
if err != nil {
log.Fatalf("Failed to create service: %v", err)
}
defer service.Close()

// Create request with transfer details
request := &transferv1.CreateTransferRequest{
Transfer: &transferv1.Transfer{
Owner: service.Group(), // Current group from service context
From: "GBZH4LMGAYUDNFPNFGOBKU76DDRJHIAKGKGO2LNZFLQB6DMKV7EYHT", // Source ledger address
To: "GCWNBLOHV5DKRG5UXKMO5IDAJLVSRRPGZJ5REWQPCT2LGXVQZQGWE3F", // Destination ledger address
Amount: &typev1.Amount{
Token: &typev1.Token{
Code: "USDC",
Issuer: "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
Ledger: typev1.Ledger_LEDGER_STELLAR,
},
Value: &typev1.Decimal{Value: "100.50"},
},
Description: "Payment for invoice #1234", // Optional reason for the transfer
IncludeInLedger: true, // Include description in on-chain transaction
},
}

// Call the CreateTransfer method
transfer, err := service.CreateTransfer(ctx, request)
if err != nil {
log.Fatalf("CreateTransfer failed: %v", err)
}

// Transfer has been created and submitted on-chain
log.Printf("Transfer created successfully:")
log.Printf(" Name: %s", transfer.Name)
log.Printf(" Number: %s", transfer.Number)
log.Printf(" State: %s", transfer.State)
log.Printf(" Fee: %s", transfer.Fee.Amount.Value)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import co.meshtrade.api.type.v1.Amount.Amount;
import co.meshtrade.api.type.v1.Decimal.Decimal;
import co.meshtrade.api.type.v1.Ledger;
import co.meshtrade.api.type.v1.Type.Token;
import co.meshtrade.api.wallet.transfer.v1.TransferService;
import co.meshtrade.api.wallet.transfer.v1.Service.CreateTransferRequest;
import co.meshtrade.api.wallet.transfer.v1.Transfer.Transfer;

import java.util.Optional;

public class CreateTransferExample {
public static void main(String[] args) {
// Default configuration is used and credentials come from MESH_API_CREDENTIALS
// environment variable or default discovery methods. Zero config required
// unless you want custom configuration.
try (TransferService service = new TransferService()) {
// Create request with transfer details
CreateTransferRequest request = CreateTransferRequest.newBuilder()
.setTransfer(Transfer.newBuilder()
.setOwner(service.group()) // Current group from service context
.setFrom("GBZH4LMGAYUDNFPNFGOBKU76DDRJHIAKGKGO2LNZFLQB6DMKV7EYHT") // Source ledger address
.setTo("GCWNBLOHV5DKRG5UXKMO5IDAJLVSRRPGZJ5REWQPCT2LGXVQZQGWE3F") // Destination ledger address
.setAmount(Amount.newBuilder()
.setToken(Token.newBuilder()
.setCode("USDC")
.setIssuer("GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN")
.setLedger(Ledger.LEDGER_STELLAR)
.build())
.setValue(Decimal.newBuilder()
.setValue("100.50")
.build())
.build())
.setDescription("Payment for invoice #1234") // Optional reason for the transfer
.setIncludeInLedger(true) // Include description in on-chain transaction
.build())
.build();

// Call the CreateTransfer method
Transfer transfer = service.createTransfer(request, Optional.empty());

// Transfer has been created and submitted on-chain
System.out.println("Transfer created successfully:");
System.out.println(" Name: " + transfer.getName());
System.out.println(" Number: " + transfer.getNumber());
System.out.println(" State: " + transfer.getState());
System.out.println(" Fee: " + transfer.getFee().getAmount().getValue());
} catch (Exception e) {
System.err.println("CreateTransfer failed: " + e.getMessage());
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from meshtrade.type.v1 import Amount, Decimal, Ledger, Token
from meshtrade.wallet.transfer.v1 import (
CreateTransferRequest,
Transfer,
TransferService,
)


def main():
# Default configuration is used and credentials come from MESH_API_CREDENTIALS
# environment variable or default discovery methods. Zero config required
# unless you want custom configuration.
service = TransferService()

with service:
# Create request with transfer details
request = CreateTransferRequest(
transfer=Transfer(
owner=service.group(), # Current group from service context
from_="GBZH4LMGAYUDNFPNFGOBKU76DDRJHIAKGKGO2LNZFLQB6DMKV7EYHT", # Source ledger address
to="GCWNBLOHV5DKRG5UXKMO5IDAJLVSRRPGZJ5REWQPCT2LGXVQZQGWE3F", # Destination ledger address
amount=Amount(
token=Token(
code="USDC",
issuer="GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
ledger=Ledger.LEDGER_STELLAR,
),
value=Decimal(value="100.50"),
),
description="Payment for invoice #1234", # Optional reason for the transfer
include_in_ledger=True, # Include description in on-chain transaction
)
)

# Call the CreateTransfer method
transfer = service.create_transfer(request)

# Transfer has been created and submitted on-chain
print("Transfer created successfully:")
print(f" Name: {transfer.name}")
print(f" Number: {transfer.number}")
print(f" State: {transfer.state}")
print(f" Fee: {transfer.fee.amount.value}")


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package main

import (
"context"
"log"

transferv1 "github.com/meshtrade/api/go/wallet/transfer/v1"
)

func main() {
ctx := context.Background()

// Default configuration is used and credentials come from MESH_API_CREDENTIALS
// environment variable or default discovery methods. Zero config required
// unless you want custom configuration.
service, err := transferv1.NewTransferService()
if err != nil {
log.Fatalf("Failed to create service: %v", err)
}
defer service.Close()

// Create request with the transfer resource name
request := &transferv1.GetTransferRequest{
Name: "wallet/transfers/01HQ3K5M8XYZ2NFVJT9BKR7P4C", // Transfer resource name
}

// Call the GetTransfer method
transfer, err := service.GetTransfer(ctx, request)
if err != nil {
log.Fatalf("GetTransfer failed: %v", err)
}

// Display transfer details
log.Printf("Transfer retrieved successfully:")
log.Printf(" Name: %s", transfer.Name)
log.Printf(" Number: %s", transfer.Number)
log.Printf(" From: %s", transfer.From)
log.Printf(" To: %s", transfer.To)
log.Printf(" Amount: %s %s", transfer.Amount.Value, transfer.Amount.Token.Code)
log.Printf(" State: %s", transfer.State)
log.Printf(" Transaction: %s", transfer.Transaction)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import co.meshtrade.api.wallet.transfer.v1.TransferService;
import co.meshtrade.api.wallet.transfer.v1.Service.GetTransferRequest;
import co.meshtrade.api.wallet.transfer.v1.Transfer.Transfer;

import java.util.Optional;

public class GetTransferExample {
public static void main(String[] args) {
// Default configuration is used and credentials come from MESH_API_CREDENTIALS
// environment variable or default discovery methods. Zero config required
// unless you want custom configuration.
try (TransferService service = new TransferService()) {
// Create request with the transfer resource name
GetTransferRequest request = GetTransferRequest.newBuilder()
.setName("wallet/transfers/01HQ3K5M8XYZ2NFVJT9BKR7P4C") // Transfer resource name
.build();

// Call the GetTransfer method
Transfer transfer = service.getTransfer(request, Optional.empty());

// Display transfer details
System.out.println("Transfer retrieved successfully:");
System.out.println(" Name: " + transfer.getName());
System.out.println(" Number: " + transfer.getNumber());
System.out.println(" From: " + transfer.getFrom());
System.out.println(" To: " + transfer.getTo());
System.out.println(" Amount: " + transfer.getAmount().getValue()
+ " " + transfer.getAmount().getToken().getCode());
System.out.println(" State: " + transfer.getState());
System.out.println(" Transaction: " + transfer.getTransaction());
} catch (Exception e) {
System.err.println("GetTransfer failed: " + e.getMessage());
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from meshtrade.wallet.transfer.v1 import (
GetTransferRequest,
TransferService,
)


def main():
# Default configuration is used and credentials come from MESH_API_CREDENTIALS
# environment variable or default discovery methods. Zero config required
# unless you want custom configuration.
service = TransferService()

with service:
# Create request with the transfer resource name
request = GetTransferRequest(
name="wallet/transfers/01HQ3K5M8XYZ2NFVJT9BKR7P4C", # Transfer resource name
)

# Call the GetTransfer method
transfer = service.get_transfer(request)

# Display transfer details
print("Transfer retrieved successfully:")
print(f" Name: {transfer.name}")
print(f" Number: {transfer.number}")
print(f" From: {transfer.from_}")
print(f" To: {transfer.to}")
print(f" Amount: {transfer.amount.value} {transfer.amount.token.code}")
print(f" State: {transfer.state}")
print(f" Transaction: {transfer.transaction}")


if __name__ == "__main__":
main()
Loading