https://api.trustlesswork.comLoading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
/**
* The base URL for the Trustless Work API
*/
export type baseURL =
| "https://api.trustlesswork.com"
| "https://dev.api.trustlesswork.com";
/**
* Escrow Type
*/
export type EscrowType = "single-release" | "multi-release";
/**
* Http Method
*/
export type HttpMethod = "get" | "post" | "put" | "delete";
/**
* Unique possible statuses for a Trustless Work request
*/
export type Status = "SUCCESS" | "FAILED";
/**
* Date
*/
export type Date = {
_seconds: number;
_nanoseconds: number;
};



fund a multi-release escrow with testnet USDC
create an SDK snippet to mark milestone as done
explain the difference between approver and release signer


The escrow lifecycle is the structured flow of actions and responsibilities that secure a transaction. At Trustless Work, we break this into clear phases, ensuring transparency, adaptability, and cons

/**
* Change Milestone Status Payload, this can be a single-release or multi-release
*/
export type ChangeMilestoneStatusPayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Index of the milestone to be updated
*/
milestoneIndex: string;
/**
* New status of the milestone
*/
newStatus: string;
/**
* New evidence of work performed by the service provider.
*/
newEvidence?: string;
/**
* Address of the entity providing the service.
*/
serviceProvider: string;
};/**
* Single Release Release Funds Payload
*/
export type SingleReleaseReleaseFundsPayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Address of the user in charge of releasing the escrow funds to the service provider.
*/
releaseSigner: string;
};/**
* Multi Release Release Funds Payload
*/
export type MultiReleaseReleaseFundsPayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Address of the user in charge of releasing the escrow funds to the service provider.
*/
releaseSigner: string;
/**
* Index of the milestone to be released
*/
milestoneIndex: string;
};/**
* Get Escrow From Indexer By Contract Ids Params
*/
export type GetEscrowFromIndexerByContractIdsParams = {
/**
* IDs (addresses) that identifies the escrow contracts.
*/
contractIds: string[];
/**
* If true, the escrows will be validated on the blockchain to ensure data consistency.
* This performs an additional verification step to confirm that the escrow data
* returned from the indexer matches the current state on the blockchain.
* Use this when you need to ensure the most up-to-date and accurate escrow information.
* If you active this param, your request will take longer to complete.
*/
validateOnChain?: boolean;
};import { ApiErrorTypes } from "@/errors/enums/error.enum";
/**
* Types for Error response
*/
export type ErrorResponse = {
message: string;
code: number;
type: ApiErrorTypes;
};
/**
* Types for TW errors
*/
export type ApiError = Pick<ErrorResponse, "message" | "code">;
/**
* Types for Wallet errors
*/
export type WalletError = Pick<ErrorResponse, "message" | "code">;
/**
* Types for Request errors
*/
export type RequestError = ApiError | Error | WalletError;
/**
* Approve Milestone Payload, this can be a single-release or multi-release
*/
export type ApproveMilestonePayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Index of the milestone to be updated
*/
milestoneIndex: string;
/**
* New evidence of work performed by the service provider.
*/
newEvidence?: string;
/**
* Address of the entity requiring the service.
*/
approver: string;
};

Single-Release Escrow is a type in which all your funds are released only once, either with the resolution of a dispute or by completing all the milestones defined for it.
approveddisputereleasedresolveddisputereleasedresolvednpx trustless-work add escrows/single-release/dispute-escrow/buttonnpx trustless-work add escrows/multi-release/dispute-milestone/buttonnpx trustless-work add escrows/single-release/release-escrow/buttonnpx trustless-work add escrows/multi-release/release-milestone/button





npx trustless-work add escrows/single-release/initialize-escrow/form
// or
npx trustless-work add escrows/single-release/initialize-escrow/dialognpx trustless-work add escrows/multi-release/initialize-escrow/form
// or
npx trustless-work add escrows/multi-release/initialize-escrow/dialognpx trustless-work add escrows/single-multi-release/fund-escrow/form
// or
npx trustless-work add escrows/single-multi-release/fund-escrow/button
// or
npx trustless-work add escrows/single-multi-release/fund-escrow/dialognpx trustless-work add escrows/indicators/balance-progress/bar
// or
npx trustless-work add escrows/indicators/balance-progress/donut/**
* Resolve Dispute Payload
*/
export type SingleReleaseResolveDisputePayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Address in charge of resolving disputes within the escrow.
*/
disputeResolver: string;
/**
* Distributions of the escrow amount to the receivers.
*/
distributions: [
{
/**
* Address of the receiver
*/
address: string;
/**
* Amount to be transferred to the receiver. All the amount must be equal to the total amount of the escrow.
*/
amount: number;
},
];
};/**
* Single Release Start Dispute Payload. This starts a dispute for the entire escrow.
*/
export type SingleReleaseStartDisputePayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Address of the user signing the contract transaction
*/
signer: string;
};/**
* Multi Release Start Dispute Payload. This starts a dispute for a specific milestone.
*/
export type MultiReleaseStartDisputePayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Address of the user signing the contract transaction
*/
signer: string;
/**
* Index of the milestone to be disputed
*/
milestoneIndex: string;
};/**
* Withdraw remaining funds
*/
export type WithdrawRemainingFundsPayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Address in charge of resolving disputes within the escrow.
*/
disputeResolver: string;
/**
* Distributions of the escrow amount to the receivers.
*/
distributions: [
{
/**
* Address of the receiver
*/
address: string;
/**
* Amount to be transferred to the receiver. All the amount must be equal to the total amount of the escrow.
*/
amount: number;
},
];
};
/**
* Fund Escrow Payload, this can be a single-release or multi-release
*/
export type FundEscrowPayload = {
/**
* Amount to be transferred upon completion of escrow milestones
*/
amount: number;
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Address of the user signing the contract transaction
*/
signer: string;
};/**
* Get Escrows From Indexer By Signer Params
*/
export type GetEscrowsFromIndexerBySignerParams = {
/**
* Page number. Pagination
*/
page?: number;
/**
* Sorting direction. Sorting
*/
orderDirection?: "asc" | "desc";
/**
* Order by property. Sorting
*/
orderBy?: "createdAt" | "updatedAt" | "amount";
/**
* Created at = start date. Filtering
*/
startDate?: string;
/**
* Created at = end date. Filtering
*/
endDate?: string;
/**
* Max amount. Filtering
*/
maxAmount?: number;
/**
* Min amount. Filtering
*/
minAmount?: number;
/**
* Is active. Filtering
*/
isActive?: boolean;
/**
* Escrow that you are looking for. Filtering
*/
title?: string;
/**
* Engagement ID. Filtering
*/
engagementId?: string;
/**
* Status of the single-release escrow. Filtering
*/
status?: SingleReleaseEscrowStatus;
/**
* Type of the escrow. Filtering
*/
type?: "single-release" | "multi-release";
/**
* If true, the escrows will be validated on the blockchain to ensure data consistency.
* This performs an additional verification step to confirm that the escrow data
* returned from the indexer matches the current state on the blockchain.
* Use this when you need to ensure the most up-to-date and accurate escrow information.
* If you active this param, your request will take longer to complete.
*/
validateOnChain?: boolean;
/**
* Address of the user signing the contract transaction.
*/
signer: string;
};/**
* Multi Release Resolve Dispute Payload
*/
export type MultiReleaseResolveDisputePayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Address in charge of resolving disputes within the escrow.
*/
disputeResolver: string;
/**
* Distributions of the escrow amount to the receivers.
*/
distributions: [
{
/**
* Address of the receiver
*/
address: string;
/**
* Amount to be transferred to the receiver. All the amount must be equal to the total amount of the escrow.
*/
amount: number;
},
];
/**
* Index of the milestone to be resolved
*/
milestoneIndex: string;
};

import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const updateEscrowFromTxHash = async (txHash) => {
const response = await http.post("/indexer/update-from-txHash", { txHash });
return response.data;
};import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async (addresses: string[]) => {
const response = await http.get("/helper/get-multiple-escrow-balance", {
params: { addresses },
});
return response;
};
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
const contractIds = [
"CCR6HLU3LQMXOESNA6TOS2RZKGEBWQG3EN5FMZNC43RVXZWTTDCZ...",
"CCA7WTCVCQ5JPKNIFSHPSJLJ3FJ3GKPNEVAIHP6T..."
];
const validateOnChain = true;
const params = new URLSearchParams();
contractIds.forEach(id => params.append("contractIds[]", id));
params.append("signer", signer);
params.append("validateOnChain", validateOnChain.toString());
const response = await http.get(`/helper/get-escrow-by-contract-ids?${params.toString()}`);
return response;
}npx trustless-work add escrows/single-multi-release/approve-milestone/form
// or
npx trustless-work add escrows/single-release/resolve-dispute/form
// or
npx trustless-work add escrows/multi-release/resolve-dispute/form
// or
npx trustless-work add escrows/single-multi-release/change-milestone-status/form
// or
npx trustless-work add escrows/multi-release/withdraw-remaining-funds/form
// or
npx trustless-work add escrows/single-release/update-escrow/form
// or
npx trustless-work add escrows/multi-release/update-escrow/form
// or

{
"txHash": "your-txHash-value"
}/**
* Get Escrows From Indexer By Role Params
*/
export type GetEscrowsFromIndexerByRoleParams = {
/**
* Page number. Pagination
*/
page?: number;
/**
* Sorting direction. Sorting
*/
orderDirection?: "asc" | "desc";
/**
* Order by property. Sorting
*/
orderBy?: "createdAt" | "updatedAt" | "amount";
/**
* Created at = start date. Filtering
*/
startDate?: string;
/**
* Created at = end date. Filtering
*/
endDate?: string;
/**
* Max amount. Filtering
*/
maxAmount?: number;
/**
* Min amount. Filtering
*/
minAmount?: number;
/**
* Is active. Filtering
*/
isActive?: boolean;
/**
* Escrow that you are looking for. Filtering
*/
title?: string;
/**
* Engagement ID. Filtering
*/
engagementId?: string;
/**
* Status of the single-release escrow. Filtering
*/
status?: SingleReleaseEscrowStatus;
/**
* Type of the escrow. Filtering
*/
type?: EscrowType;
/**
* If true, the escrows will be validated on the blockchain to ensure data consistency.
* This performs an additional verification step to confirm that the escrow data
* returned from the indexer matches the current state on the blockchain.
* Use this when you need to ensure the most up-to-date and accurate escrow information.
* If you active this param, your request will take longer to complete.
*/
validateOnChain?: boolean;
/**
* Role of the user. Required
*/
role: Role;
/**
* Address of the owner of the escrows. If you want to get all escrows from a specific role, you can use this parameter. But with this parameter, you can't use the signer parameter.
*/
roleAddress: string;
};
import { Date, EscrowType, Status } from "./types";
import {
Flags,
MultiReleaseEscrow,
MultiReleaseMilestone,
Roles,
SingleReleaseEscrow,
SingleReleaseMilestone,
Trustline,
} from "./types.entity";
/**
* Escrow's Response like fund, release, change, etc ...
*/
export type EscrowRequestResponse = {
/**
* Status of the request
*/
status: Status;
/**
* Unsigned transaction
*/
unsignedTransaction?: string;
};
/**
* Send Transaction Response
*/
export type SendTransactionResponse = {
/**
* Status of the request
*/
status: Status;
/**
* Message of the request
*/
message: string;
};
/**
* Initialize Escrow Response
*/
export type InitializeSingleReleaseEscrowResponse = EscrowRequestResponse & {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Escrow data
*/
escrow: SingleReleaseEscrow;
/**
* Message of the request
*/
message: string;
};
/**
* Initialize Multi Release Escrow Response
*/
export type InitializeMultiReleaseEscrowResponse =
InitializeSingleReleaseEscrowResponse & {
/**
* Escrow data
*/
escrow: MultiReleaseEscrow;
};
/**
* Update Escrow Response
*/
export type UpdateSingleReleaseEscrowResponse =
InitializeSingleReleaseEscrowResponse;
/**
* Update Multi Release Escrow Response
*/
export type UpdateMultiReleaseEscrowResponse =
InitializeMultiReleaseEscrowResponse;
/**
* Get Balances Response
*/
export type GetEscrowBalancesResponse = {
/**
* Address of the escrow
*/
address: string;
/**
* Balance of the escrow
*/
balance: number;
};
/**
* Get Escrows From Indexer Response
*/
export type GetEscrowsFromIndexerResponse = {
signer?: string;
contractId?: string;
engagementId: string;
title: string;
roles: Roles;
description: string;
amount: number;
platformFee: number;
balance?: number;
milestones:
| SingleReleaseMilestone[]
| (MultiReleaseMilestone[] & { disputeStartedBy: Roles });
flags?: Flags;
trustline: Trustline & { name: string };
receiverMemo?: number;
disputeStartedBy?: string;
fundedBy?: string;
isActive?: boolean;
approverFunds?: string;
receiverFunds?: string;
user: string;
createdAt: Date;
updatedAt: Date;
type: EscrowType;
};
/**
* Response for updating escrow from transaction hash
*/
export type UpdateFromTxHashResponse = {
/**
* Status of the request
*/
status: "SUCCESS" | "FAILED";
/**
* Message describing the result
*/
message: string;
};https://api.trustlesswork.comhttps://dev.api.trustlesswork.comimport axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.post(
"/escrow/multi-release/release-milestone-funds",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.post(
"/escrow/single-release/resolve-dispute",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.post(
"/escrow/multi-release/approve-milestone",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.post(
"/escrow/single-release/approve-milestone",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.post(
"/escrow/multi-release/fund-escrow",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.post(
"/escrow/multi-release/resolve-milestone-dispute",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
// Execute the endpoint
const response = await http.post(
"/escrow/multi-release/dispute-milestone",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.post(
"/escrow/single-release/release-funds",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
// Execute the endpoint
const response = await http.post(
"/escrow/single-release/dispute-escrow",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.post(
"/escrow/single-release/fund-escrow",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.post(
"/escrow/multi-release/withdraw-remaining-funds",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.post(
"/escrow/multi-release/change-milestone-status",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.post(
"/escrow/single-release/change-milestone-status",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.post(
"/any-endpoint",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network <--------------- THIS
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}This endpoint allows you to change the properties of an escrow as long as a series of requirements are met, which will be mentioned in this section.









stellar-cli request-tokens --network testnet --public-key <Your Public Key># Core
npx trustless-work add wallet-kit
npx trustless-work add tanstack
npx trustless-work add providers
# Actions (pick what you need)
npx trustless-work add escrows/single-release
# npx trustless-work add escrows/multi-release
# npx trustless-work add escrows/single-multi-release
# Optional utility modules
npx trustless-work add handle-errors
npx trustless-work add helpersnpx trustless-work add wallet-kit
npx trustless-work add tanstack
npx trustless-work add providers
npx trustless-work add handle-errors
npx trustless-work add helpersimport { ReactQueryClientProvider } from "@/components/tw-blocks/providers/ReactQueryClientProvider";
import { TrustlessWorkProvider } from "@/components/tw-blocks/providers/TrustlessWork";
import { WalletProvider } from "@/components/tw-blocks/wallet-kit/WalletProvider";
import { EscrowProvider } from "@/components/tw-blocks/providers/EscrowProvider";
import { EscrowDialogsProvider } from "@/components/tw-blocks/providers/EscrowDialogsProvider";
import { EscrowAmountProvider } from "@/components/tw-blocks/providers/EscrowAmountProvider";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<ReactQueryClientProvider>
<TrustlessWorkProvider>
<WalletProvider>
<EscrowProvider>
<EscrowDialogsProvider>
<EscrowAmountProvider>
{children}
</EscrowAmountProvider>
</EscrowDialogsProvider>
</EscrowProvider>
</WalletProvider>
</TrustlessWorkProvider>
</ReactQueryClientProvider>
</body>
</html>
);
}import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
// Execute the endpoint
const response = await http.post(
"/deployer/single-release",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.put(
"/escrow/multi-release/update-escrow",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}
{
"contractId": "C...ESCROWADDRESS",
"engagementId": "order-123",
"title": "Website Development",
"description": "Build and deliver a marketing website",
"roles": {
"approver": "G...CLIENT",
"serviceProvider": "G...FREELANCER",
"releaseSigner": "G...SIGNER",
"platformAddress": "G...PLATFORM",
"disputeResolver": "G...RESOLVER",
"receiver": "G...FREELANCER"
},
"amount": 1000,
"platformFee": 0.5,
"milestones": [
{
"description": "Deliver homepage design",
"status": "Approved",
"approved": true
},
{
"description": "Deploy full website",
"status": "Pending",
"approved": false
}
],
"flags": {
"disputed": false,
"released": false,
"resolved": false
},
"trustline": {
"address": "G...USDCISSUER",
}
}{
"contractId": "C...ESCROWADDRESS",
"engagementId": "grant-456",
"title": "Research Grant",
"description": "Funding project in two phases",
"roles": {
"approver": "G...FUNDER",
"serviceProvider": "G...RESEARCHER",
"releaseSigner": "G...SIGNER",
"platformAddress": "G...PLATFORM",
"disputeResolver": "G...RESOLVER",
},
"platformFee": 0.5,
"milestones": [
{
"description": "Submit interim report",
"amount": 500,
"status": "Approved",
"flags": { "approved": true, "released": true, "disputed": false, "resolved": false },
"receiver": "G...RESEARCHER"
},
{
"description": "Publish final report",
"amount": 500,
"status": "Pending",
"flags": { "approved": false, "released": false, "disputed": false, "resolved": false },
"receiver": "G...RESEARCHER"
}
],
"trustline": {
"address": "G...USDCISSUER",
}
}npx trustless-work listconst { selectedEscrow } = useEscrowContext();
const handleSubmit = form.handleSubmit(async (payload) => {
/**
* Create the final payload for the change milestone status mutation
*
* @param payload - The payload from the form
* @returns The final payload for the change milestone status mutation
*/
const finalPayload: ChangeMilestoneStatusPayload = {
contractId: selectedEscrow?.contractId || '', // contractId from the selectedEscrow
milestoneIndex: payload.milestoneIndex,
newStatus: payload.status,
newEvidence: payload.evidence || undefined,
serviceProvider: walletAddress || '',
};
/**
* Call the change milestone status mutation
*
* @param payload - The final payload for the change milestone statusmutation
* @param type - The type of the escrow
* @param address - The address of the escrow
*/
await changeMilestoneStatus.mutateAsync({
payload: finalPayload,
type: selectedEscrow?.type || 'multi-release',
address: walletAddress || '',
});
}const { setSelectedEscrow } = useEscrowContext();
const onCardClick = (escrow: Escrow) => {
setSelectedEscrow(escrow);
dialogStates.second.setIsOpen(true);
};const { selectedEscrow, updateEscrow } = useEscrowContext();
const handleSubmit = form.handleSubmit(async (payload) => {
/**
* Call the change milestone status mutation
*
* @param payload - The final payload for the change milestone status mutation
* @param type - The type of the escrow
* @param address - The address of the escrow
*/
await changeMilestoneStatus.mutateAsync({
payload: finalPayload,
type: selectedEscrow?.type || "multi-release", // type from the selectedEscrow
address: walletAddress || "",
});
toast.success("Milestone status updated successfully");
// Update the selected escrow in the context with the new status and evidence
updateEscrow({
...selectedEscrow,
milestones: selectedEscrow?.milestones.map((milestone, index) => {
if (index === Number(payload.milestoneIndex)) {
return {
...milestone,
status: payload.status,
evidence: payload.evidence || undefined,
};
}
return milestone;
}),
});
}npx trustless-work add escrowsnpx trustless-work add escrows/single-releaseimport axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
// Execute the endpoint
const response = await http.post(
"/deployer/multi-release",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
const data = await http.get(
"/escrow/single-release/get-escrows-by-role?role=approver?roleAddress=GPUACN...." 👈🏼 // All required parameters are passed at the query level.
);
return data;
}import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
const data = await http.get(
"/escrow/single-release/get-escrows-by-signer?signer=GPUACN...." 👈🏼 // All required parameters are passed at the query level.
);
return data;
}


This endpoint allows you to change the properties of an escrow as long as a series of requirements are met, which will be mentioned in this section.


/**
* Trustline
*/
export type Trustline = {
/**
* Symbol of the token, example: USDC, EURC, etc...
*/
symbol: string;
/**
* Public address establishing permission to accept and use a specific token.
*/
address: string;
};/**
* Single Release Initialize Escrow Payload
*/
export type InitializeSingleReleaseEscrowPayload = {
/**
* Address of the user signing the contract transaction
*/
signer: string;
/**
* Unique identifier for the escrow
*/
engagementId: string;
/**
* Name of the escrow
*/
title: string;
/**
* Roles that make up the escrow structure
*/
roles: {
/**
* Address of the entity requiring the service.
*/
approver: string;
/**
* Address of the entity providing the service.
*/
serviceProvider: string;
/**
* Address of the entity that owns the escrow
*/
platformAddress: string;
/**
* Address of the user in charge of releasing the escrow funds to the service provider.
*/
releaseSigner: string;
/**
* Address in charge of resolving disputes within the escrow.
*/
disputeResolver: string;
/**
* Address where escrow proceeds will be sent to
*/
receiver: string;
};
/**
* Text describing the function of the escrow
*/
description: string;
/**
* Amount to be transferred upon completion of escrow milestones
*/
amount: number;
/**
* Commission that the platform will receive when the escrow is completed
*/
platformFee: number;
/**
* Flags validating certain escrow life states
*/
flags?: {
/**
* Flag indicating that an escrow is in dispute.
*/
disputed?: boolean;
/**
* Flag indicating that escrow funds have already been released.
*/
released?: boolean;
/**
* Flag indicating that a disputed escrow has already been resolved.
*/
resolved?: boolean;
/**
* Flag indicating whether a milestone has been approved by the approver.
*/
approved?: boolean;
};
/**
* Information on the trustline that will manage the movement of funds in escrow
*/
trustline: {
/**
* Public address establishing permission to accept and use a specific token.
*/
address: string;
/**
* Official abbreviation representing the token in wallets, exchanges, and documentation.
*/
symbol: string;
};
/**
* Objectives to be completed to define the escrow as completed
*/
milestones: {
/**
* Text describing the function of the milestone
*/
description: string;
}[];
};/**
* Multi Release Initialize Escrow Payload
*/
export type InitializeMultiReleaseEscrowPayload = {
/**
* Address of the user signing the contract transaction
*/
signer: string;
/**
* Unique identifier for the escrow
*/
engagementId: string;
/**
* Name of the escrow
*/
title: string;
/**
* Roles that make up the escrow structure (without receiver, as each milestone has its own receiver)
*/
roles: {
/**
* Address of the entity requiring the service.
*/
approver: string;
/**
* Address of the entity providing the service.
*/
serviceProvider: string;
/**
* Address of the entity that owns the escrow
*/
platformAddress: string;
/**
* Address of the user in charge of releasing the escrow funds to the service provider.
*/
releaseSigner: string;
/**
* Address in charge of resolving disputes within the escrow.
*/
disputeResolver: string;
};
/**
* Text describing the function of the escrow
*/
description: string;
/**
* Commission that the platform will receive when the escrow is completed
*/
platformFee: number;
/**
* Information on the trustline that will manage the movement of funds in escrow
*/
trustline: {
/**
* Public address establishing permission to accept and use a specific token.
*/
address: string;
/**
* Official abbreviation representing the token in wallets, exchanges, and documentation.
*/
symbol: string;
};
/**
* Objectives to be completed to define the escrow as completed
*/
milestones: {
/**
* Text describing the function of the milestone
*/
description: string;
/**
* Amount to be transferred upon completion of this milestone
*/
amount: number;
/**
* Address where milestone proceeds will be sent to
*/
receiver: string;
}[];
};/**
* Single Release Escrow
*/
export type SingleReleaseEscrow = {
/**
* Address of the user signing the contract transaction
*/
signer: string;
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Unique identifier for the escrow
*/
engagementId: string;
/**
* Name of the escrow
*/
title: string;
/**
* Roles that make up the escrow structure
*/
roles: Roles;
/**
* Text describing the function of the escrow
*/
description: string;
/**
* Amount to be transferred upon completion of escrow milestones
*/
amount: number;
/**
* Commission that the platform will receive when the escrow is completed
*/
platformFee: number;
/**
* Amount of the token (XLM, USDC, EURC, etc) in the smart contract.
*/
balance: number;
/**
* Objectives to be completed to define the escrow as completed
*/
milestones: SingleReleaseMilestone[];
/**
* Flags validating certain escrow life states
*/
flags?: Flags;
/**
* Information on the trustline that will manage the movement of funds in escrow
*/
trustline: Trustline;
};
/**
* Multi Release Escrow
*/
export type MultiReleaseEscrow = Omit<
SingleReleaseEscrow,
"milestones" | "flags" | "amount" | "roles"
> & {
milestones: MultiReleaseMilestone[];
roles: Omit<Roles, "receiver">;
};/**
* Milestone
*/
type BaseMilestone = {
/**
* Text describing the function of the milestone.
*/
description: string;
/**
* Milestone status. Ex: Approved, In dispute, etc...
*/
status?: string;
/**
* Evidence of work performed by the service provider.
*/
evidence?: string;
};
/**
* Single Release Milestone
*/
export type SingleReleaseMilestone = BaseMilestone & {
/**
* Approved flag, only if the escrow is single-release
*/
approved?: boolean;
};
/**
* Multi Release Milestone
*/
export type MultiReleaseMilestone = BaseMilestone & {
/**
* Amount to be transferred upon completion of this milestone
*/
amount: number;
/**
* Address where milestone proceeds will be sent to
*/
receiver: string;
/**
* Flags validating certain milestone life states, only if the escrow is multi-release
*/
flags?: Flags;
};/**
* Flags
*/
export type Flags = {
/**
* Flag indicating that an escrow is in dispute.
*/
disputed?: boolean;
/**
* Flag indicating that escrow funds have already been released.
*/
released?: boolean;
/**
* Flag indicating that a disputed escrow has already been resolved.
*/
resolved?: boolean;
/**
* Flag indicating whether a milestone has been approved by the approver.
*/
approved?: boolean;
};
/**
* Roles
*/
export type Roles = {
/**
* Address of the entity requiring the service.
*/
approver: string;
/**
* Address of the entity providing the service.
*/
serviceProvider: string;
/**
* Address of the entity that owns the escrow
*/
platformAddress: string;
/**
* Address of the user in charge of releasing the escrow funds to the service provider.
*/
releaseSigner: string;
/**
* Address in charge of resolving disputes within the escrow.
*/
disputeResolver: string;
/**
* Address where escrow proceeds will be sent to (In the “Multi-Release” version,
this role is at the milestone level.)
*/
receiver: string;
};
/**
* Role
*/
export type Role =
| "approver"
| "serviceProvider"
| "platformAddress"
| "releaseSigner"
| "disputeResolver"
| "receiver"
| "signer";mainNetdevelopmentnpx trustless-work initnpx trustless-work add wallet-kitimport { WalletButton } from "@/components/tw-blocks/wallet-kit/WalletButtons";
export default function HomePage() {
return (
<div className="container mx-auto py-8">
<div className="flex justify-between items-center mb-8">
<h1 className="text-3xl font-bold">My Escrows</h1>
<WalletButton />
</div>
</div>
);
}"use client"; // make sure this is a client component
import React from "react";
import {
// development environment = "https://dev.api.trustlesswork.com"
development,
// mainnet environment = "https://api.trustlesswork.com"
mainNet,
TrustlessWorkConfig,
} from "@trustless-work/escrow";
interface TrustlessWorkProviderProps {
children: React.ReactNode;
}
export function TrustlessWorkProvider({
children,
}: TrustlessWorkProviderProps) {
/**
* Get the API key from the environment variables
*/
const apiKey = process.env.NEXT_PUBLIC_API_KEY || "";
return (
<TrustlessWorkConfig baseURL={development} apiKey={apiKey}>
{children}
</TrustlessWorkConfig>
);
}
import axios from "axios";
const http = axios.create({
baseURL: "https://dev.api.trustlesswork.com",
timeout: 10000,
headers: {
"Content-Type": "application/json",
"x-api-key": your_api_key,
},
});
export const useExample = async () => {
// Get the signer address
const { address } = await kit.getAddress();
const response = await http.put(
"/escrow/single-release/update-escrow",
{
// body requested for the endpoint
},
);
// Get the unsigned transaction hash
const { unsignedTransaction } = response.data;
// Sign the transaction by wallet
const { signedTxXdr } = await signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
// Send the transaction to Stellar Network
const tx = await http.post("/helper/send-transaction", {
signedXdr: signedTxXdr,
});
const { data } = tx;
return data;
}

/**
* Single Release Update Escrow Payload
*/
export type UpdateSingleReleaseEscrowPayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Escrow data
*/
escrow: {
/**
* Unique identifier for the escrow
*/
engagementId: string;
/**
* Name of the escrow
*/
title: string;
/**
* Roles that make up the escrow structure
*/
roles: {
/**
* Address of the entity requiring the service.
*/
approver: string;
/**
* Address of the entity providing the service.
*/
serviceProvider: string;
/**
* Address of the entity that owns the escrow
*/
platformAddress: string;
/**
* Address of the user in charge of releasing the escrow funds to the service provider.
*/
releaseSigner: string;
/**
* Address in charge of resolving disputes within the escrow.
*/
disputeResolver: string;
/**
* Address where escrow proceeds will be sent to
*/
receiver: string;
};
/**
* Text describing the function of the escrow
*/
description: string;
/**
* Amount to be transferred upon completion of escrow milestones
*/
amount: number;
/**
* Commission that the platform will receive when the escrow is completed
*/
platformFee: number;
/**
* Objectives to be completed to define the escrow as completed
*/
milestones: {
/**
* Text describing the function of the milestone.
*/
description: string;
/**
* Milestone status. Ex: Approved, In dispute, etc...
*/
status?: string;
/**
* Evidence of work performed by the service provider.
*/
evidence?: string;
/**
* Approved flag, only if the escrow is single-release
*/
approved?: boolean;
}[];
/**
* Flags validating certain escrow life states
*/
flags?: {
/**
* Flag indicating that an escrow is in dispute.
*/
disputed?: boolean;
/**
* Flag indicating that escrow funds have already been released.
*/
released?: boolean;
/**
* Flag indicating that a disputed escrow has already been resolved.
*/
resolved?: boolean;
/**
* Flag indicating whether a milestone has been approved by the approver.
*/
approved?: boolean;
};
/**
* Information on the trustline that will manage the movement of funds in escrow
*/
trustline: {
/**
* Symbol of the token, example: USDC, EURC, etc...
*/
symbol: string;
/**
* Public address establishing permission to accept and use a specific token.
*/
address: string;
};
/**
* Whether the escrow is active. This comes from DB, not from the blockchain.
*/
isActive?: boolean;
};
/**
* Address of the user signing the contract transaction
*/
signer: string;
};/**
* Multi Release Update Escrow Payload
*/
export type UpdateMultiReleaseEscrowPayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Escrow data
*/
escrow: {
/**
* Unique identifier for the escrow
*/
engagementId: string;
/**
* Name of the escrow
*/
title: string;
/**
* Roles that make up the escrow structure (without receiver, as each milestone has its own receiver)
*/
roles: {
/**
* Address of the entity requiring the service.
*/
approver: string;
/**
* Address of the entity providing the service.
*/
serviceProvider: string;
/**
* Address of the entity that owns the escrow
*/
platformAddress: string;
/**
* Address of the user in charge of releasing the escrow funds to the service provider.
*/
releaseSigner: string;
/**
* Address in charge of resolving disputes within the escrow.
*/
disputeResolver: string;
};
/**
* Text describing the function of the escrow
*/
description: string;
/**
* Commission that the platform will receive when the escrow is completed
*/
platformFee: number;
/**
* Objectives to be completed to define the escrow as completed
*/
milestones: {
/**
* Text describing the function of the milestone.
*/
description: string;
/**
* Milestone status. Ex: Approved, In dispute, etc...
*/
status?: string;
/**
* Evidence of work performed by the service provider.
*/
evidence?: string;
/**
* Amount to be transferred upon completion of this milestone
*/
amount: number;
/**
* Address where milestone proceeds will be sent to
*/
receiver: string;
/**
* Flags validating certain milestone life states, only if the escrow is multi-release
*/
flags?: {
/**
* Flag indicating that an escrow is in dispute.
*/
disputed?: boolean;
/**
* Flag indicating that escrow funds have already been released.
*/
released?: boolean;
/**
* Flag indicating that a disputed escrow has already been resolved.
*/
resolved?: boolean;
/**
* Flag indicating whether a milestone has been approved by the approver.
*/
approved?: boolean;
};
}[];
/**
* Information on the trustline that will manage the movement of funds in escrow
*/
trustline: {
/**
* Symbol of the token, example: USDC, EURC, etc...
*/
symbol: string;
/**
* Public address establishing permission to accept and use a specific token.
*/
address: string;
};
/**
* Whether the escrow is active. This comes from DB, not from the blockchain.
*/
isActive?: boolean;
};
/**
* Address of the user signing the contract transaction
*/
signer: string;
};

npx create-next-app@latestcd my-trustless-appnpm install @trustless-work/blocksnpx trustless-work init# Required: Your Trustless Work API key
NEXT_PUBLIC_API_KEY=your_api_key_herenpx trustless-work add wallet-kitreturn (
<WalletProvider>{children}</WalletProvider>
);"use client";
import { WalletButton } from "@/components/tw-blocks/wallet-kit/WalletButtons";
export default function Home() {
return (
<div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
<header className="flex justify-between items-center w-full">
<h2 className="text-2xl font-bold">Trustless Work</h2>
{/* Wallet Button */}
<WalletButton />
</header>
</div>
);
}npx trustless-work add helpersnpx trustless-work add tanstacknpx trustless-work add handle-errorsnpx trustless-work add providersnpx trustless-work add escrows/single-releasenpx trustless-work add escrows/single-multi-releasenpx trustless-work add escrows/escrows-by-role/cardsreturn (
<div className="flex items-start justify-start flex-col gap-2 w-full">
{/* You can add the buttons here, using the buttons from the blocks. These actions are conditional based on the escrow flags and the user roles. */}
{hasConditionalButtons && (
<div className="flex flex-col gap-2 w-full">
{/* UpdateEscrowDialog component should be rendered based on the escrow type. It means that if the selectedEscrow.type is "single-release", then the UpdateEscrowDialog (from the single-release block) component should be rendered. If the selectedEscrow.type is "multi-release", then the UpdateEscrowDialog (from the multi-release block) component should be rendered. */}
{/* {shouldShowEditButton && <UpdateEscrowDialog />} */}
{/* Works only with single-release escrows */}
{/* Only appears if the escrow has balance */}
{/* {shouldShowDisputeButton && <DisputeEscrowButton />} */}
{/* Works only with single-release escrows */}
{/* Only appears if the escrow is disputed */}
{/* {shouldShowResolveButton && <ResolveDisputeDialog />} */}
{/* Works only with single-release escrows */}
{/* Only appears if all the milestones are approved */}
{/* {shouldShowReleaseFundsButton && <ReleaseEscrowButton />} */}
</div>
)}
<FundEscrowDialog />
</div>
);// If you need both types, you should import both versions to update escrow
import { UpdateEscrowDialog } from "../../single-release/update-escrow/dialog/UpdateEscrow";
/* import { UpdateEscrowDialog as UpdateEscrowDialogMultiRelease } from "../../multi-release/update-escrow/dialog/UpdateEscrow"; */
import { FundEscrowDialog } from "../../single-multi-release/fund-escrow/dialog/FundEscrow";
import { DisputeEscrowButton } from "../../single-release/dispute-escrow/button/DisputeEscrow";
import { ResolveDisputeDialog } from "../../single-release/resolve-dispute/dialog/ResolveDispute";
import { ReleaseEscrowButton } from "../../single-release/release-escrow/button/ReleaseEscrow";
return (
<div className="flex items-start justify-start flex-col gap-2 w-full">
{/* You can add the buttons here, using the buttons from the blocks. These actions are conditional based on the escrow flags and the user roles. */}
{hasConditionalButtons && (
<div className="flex flex-col gap-2 w-full">
{/* UpdateEscrowDialog component should be rendered based on the escrow type. It means that if the selectedEscrow.type is "single-release", then the UpdateEscrowDialog (from the single-release block) component should be rendered. If the selectedEscrow.type is "multi-release", then the UpdateEscrowDialog (from the multi-release block) component should be rendered. */}
{shouldShowEditButton && <UpdateEscrowDialog />}
{/* Works only with single-release escrows */}
{shouldShowDisputeButton && <DisputeEscrowButton />}
{/* Works only with single-release escrows */}
{shouldShowResolveButton && <ResolveDisputeDialog />}
{/* Works only with single-release escrows */}
{shouldShowReleaseFundsButton && <ReleaseEscrowButton />}
</div>
)}
<FundEscrowDialog />
</div>
);import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import { ReactQueryClientProvider } from "@/components/tw-blocks/providers/ReactQueryClientProvider";
import { TrustlessWorkProvider } from "@/components/tw-blocks/providers/TrustlessWork";
import { WalletProvider } from "@/components/tw-blocks/wallet-kit/WalletProvider";
import { EscrowProvider } from "@/components/tw-blocks/providers/EscrowProvider";
import { EscrowDialogsProvider } from "@/components/tw-blocks/providers/EscrowDialogsProvider";
import { EscrowAmountProvider } from "@/components/tw-blocks/providers/EscrowAmountProvider";
import { Toaster } from "@/components/ui/sonner";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body
// optional: use geistSans.variable and geistMono.variable
className="antialiased"
>
<ReactQueryClientProvider>
<TrustlessWorkProvider>
<WalletProvider>
<EscrowProvider>
<EscrowDialogsProvider>
<EscrowAmountProvider>
{children}
<Toaster />
</EscrowAmountProvider>
</EscrowDialogsProvider>
</EscrowProvider>
</WalletProvider>
</TrustlessWorkProvider>
</ReactQueryClientProvider>
</body>
</html>
);
}"use client";
import { EscrowsByRoleCards } from "@/components/tw-blocks/escrows/escrows-by-role/cards/EscrowsCards";
import { InitializeEscrowDialog } from "@/components/tw-blocks/escrows/single-release/initialize-escrow/dialog/InitializeEscrow";
import { WalletButton } from "@/components/tw-blocks/wallet-kit/WalletButtons";
export default function Home() {
return (
<div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
<header className="flex justify-between items-center w-full">
<h2 className="text-2xl font-bold">Trustless Work</h2>
<WalletButton />
</header>
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
<div className="container">
<div className="flex w-full mb-4 justify-end">
<div className="flex w-1/6">
<InitializeEscrowDialog />
</div>
</div>
<EscrowsByRoleCards />
</div>
</main>
</div>
);
}
import { EscrowType, SingleReleaseEscrowStatus } from "./types";
import { MultiReleaseEscrow, Role, SingleReleaseEscrow } from "./types.entity";
/**
* Documentation: https://docs.trustlesswork.com/trustless-work/developer-resources/quickstart/integration-demo-project/entities
*/
// ----------------- Milestone Payloads -----------------
/**
* Single Release Milestone Payload
*/
export type SingleReleaseMilestonePayload = {
/**
* Text describing the function of the milestone
*/
description: string;
};
/**
* Multi Release Milestone Payload
*/
export type MultiReleaseMilestonePayload = {
/**
* Text describing the function of the milestone
*/
description: string;
/**
* Amount to be transferred upon completion of this milestone
*/
amount: number;
/**
* Address where milestone proceeds will be sent to
*/
receiver: string;
};
// ----------------- Initialize Escrow -----------------
/**
* Single Release Initialize Escrow Payload
*/
export type InitializeSingleReleaseEscrowPayload = Omit<
SingleReleaseEscrow,
"contractId" | "balance" | "milestones"
> & {
/**
* Objectives to be completed to define the escrow as completed
*/
milestones: SingleReleaseMilestonePayload[];
};
/**
* Multi Release Initialize Escrow Payload
*/
export type InitializeMultiReleaseEscrowPayload = Omit<
MultiReleaseEscrow,
"contractId" | "balance" | "milestones"
> & {
/**
* Objectives to be completed to define the escrow as completed
*/
milestones: MultiReleaseMilestonePayload[];
};
// ----------------- Update Escrow -----------------
/**
* Single Release Update Escrow Payload
*/
export type UpdateSingleReleaseEscrowPayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Escrow data
*/
escrow: Omit<SingleReleaseEscrow, "contractId" | "signer" | "balance"> & {
/**
* Whether the escrow is active. This comes from DB, not from the blockchain.
*/
isActive?: boolean;
};
/**
* Address of the user signing the contract transaction
*/
signer: string;
};
/**
* Multi Release Update Escrow Payload
*/
export type UpdateMultiReleaseEscrowPayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Escrow data
*/
escrow: Omit<MultiReleaseEscrow, "contractId" | "signer" | "balance"> & {
/**
* Whether the escrow is active. This comes from DB, not from the blockchain.
*/
isActive?: boolean;
};
/**
* Address of the user signing the contract transaction
*/
signer: string;
};
// ----------------- Change Milestone Status -----------------
/**
* Change Milestone Status Payload, this can be a single-release or multi-release
*/
export type ChangeMilestoneStatusPayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Index of the milestone to be updated
*/
milestoneIndex: string;
/**
* New status of the milestone
*/
newStatus: string;
/**
* New evidence of work performed by the service provider.
*/
newEvidence?: string;
/**
* Address of the entity providing the service.
*/
serviceProvider: string;
};
// ----------------- Approve Milestone -----------------
/**
* Approve Milestone Payload, this can be a single-release or multi-release
*/
export type ApproveMilestonePayload = Omit<
ChangeMilestoneStatusPayload,
"serviceProvider" | "newStatus"
> & {
/**
* Address of the entity requiring the service.
*/
approver: string;
};
// ----------------- Start Dispute -----------------
/**
* Single Release Start Dispute Payload. This starts a dispute for the entire escrow.
*/
export type SingleReleaseStartDisputePayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Address of the user signing the contract transaction
*/
signer: string;
};
/**
* Multi Release Start Dispute Payload. This starts a dispute for a specific milestone.
*/
export type MultiReleaseStartDisputePayload =
SingleReleaseStartDisputePayload & {
/**
* Index of the milestone to be disputed
*/
milestoneIndex: string;
};
// ----------------- Resolve Dispute -----------------
/**
* Resolve Dispute Payload
*/
export type SingleReleaseResolveDisputePayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Address in charge of resolving disputes within the escrow.
*/
disputeResolver: string;
/**
* Distributions of the escrow amount to the receivers.
*/
distributions: [
{
/**
* Address of the receiver
*/
address: string;
/**
* Amount to be transferred to the receiver. All the amount must be equal to the total amount of the escrow.
*/
amount: number;
},
];
};
/**
* Multi Release Resolve Dispute Payload
*/
export type MultiReleaseResolveDisputePayload =
SingleReleaseResolveDisputePayload & {
/**
* Index of the milestone to be resolved
*/
milestoneIndex: string;
};
// ----------------- Withdraw Remaining Funds -----------------
/**
* Withdraw remaining funds
*/
export type WithdrawRemainingFundsPayload = SingleReleaseResolveDisputePayload;
// ----------------- Fund Escrow -----------------
/**
* Fund Escrow Payload, this can be a single-release or multi-release
*/
export type FundEscrowPayload = {
/**
* Amount to be transferred upon completion of escrow milestones
*/
amount: number;
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Address of the user signing the contract transaction
*/
signer: string;
};
// ----------------- Get Escrows From Indexer -----------------
/**
* Get Escrows From Indexer Params
*/
export type GetEscrowsFromIndexerParams = {
/**
* Page number. Pagination
*/
page?: number;
/**
* Sorting direction. Sorting
*/
orderDirection?: "asc" | "desc";
/**
* Order by property. Sorting
*/
orderBy?: "createdAt" | "updatedAt" | "amount";
/**
* Created at = start date. Filtering
*/
startDate?: string;
/**
* Created at = end date. Filtering
*/
endDate?: string;
/**
* Max amount. Filtering
*/
maxAmount?: number;
/**
* Min amount. Filtering
*/
minAmount?: number;
/**
* Is active. Filtering
*/
isActive?: boolean;
/**
* Escrow that you are looking for. Filtering
*/
title?: string;
/**
* Engagement ID. Filtering
*/
engagementId?: string;
/**
* Status of the single-release escrow. Filtering
*/
status?: SingleReleaseEscrowStatus;
/**
* Type of the escrow. Filtering
*/
type?: EscrowType;
/**
* If true, the escrows will be validated on the blockchain to ensure data consistency.
* This performs an additional verification step to confirm that the escrow data
* returned from the indexer matches the current state on the blockchain.
* Use this when you need to ensure the most up-to-date and accurate escrow information.
* If you active this param, your request will take longer to complete.
*/
validateOnChain?: boolean;
};
export type GetEscrowsFromIndexerBySignerParams =
GetEscrowsFromIndexerParams & {
/**
* Address of the user signing the contract transaction.
*/
signer: string;
};
export type GetEscrowsFromIndexerByRoleParams = GetEscrowsFromIndexerParams & {
/**
* Role of the user. Required
*/
role: Role;
/**
* Address of the owner of the escrows. If you want to get all escrows from a specific role, you can use this parameter. But with this parameter, you can't use the signer parameter.
*/
roleAddress: string;
};
export type GetEscrowFromIndexerByContractIdsParams = {
/**
* IDs (addresses) that identifies the escrow contracts.
*/
contractIds: string[];
/**
* If true, the escrows will be validated on the blockchain to ensure data consistency.
* This performs an additional verification step to confirm that the escrow data
* returned from the indexer matches the current state on the blockchain.
* Use this when you need to ensure the most up-to-date and accurate escrow information.
* If you active this param, your request will take longer to complete.
*/
validateOnChain?: boolean;
};
// ----------------- Release Funds -----------------
/**
* Single Release Release Funds Payload
*/
export type SingleReleaseReleaseFundsPayload = {
/**
* ID (address) that identifies the escrow contract
*/
contractId: string;
/**
* Address of the user in charge of releasing the escrow funds to the service provider.
*/
releaseSigner: string;
};
/**
* Multi Release Release Funds Payload
*/
export type MultiReleaseReleaseFundsPayload =
SingleReleaseReleaseFundsPayload & {
/**
* Index of the milestone to be released
*/
milestoneIndex: string;
};
// ----------------- Get Balance -----------------
/**
* Get Balance Params
*/
export type GetBalanceParams = {
/**
* Addresses of the escrows to get the balance
*/
addresses: string[];
};
// ----------------- Update From Transaction Hash -----------------
/**
* Payload for updating escrow data from a transaction hash.
*/
export type UpdateFromTxHashPayload = {
/**
* Transaction hash to be used for the update.
*/
txHash: string;
};npm install @creit.tech/stellar-wallets-kitimport {
StellarWalletsKit,
WalletNetwork,
FREIGHTER_ID,
AlbedoModule,
FreighterModule,
} from "@creit.tech/stellar-wallets-kit";
/**
* Main configuration for Stellar Wallet Kit
* This kit supports multiple wallet types including Freighter and Albedo
* Configure for TESTNET during development and MAINNET for production
*/
export const kit: StellarWalletsKit = new StellarWalletsKit({
network: WalletNetwork.TESTNET,
selectedWalletId: FREIGHTER_ID,
modules: [new FreighterModule(), new AlbedoModule()],
});
/**
* Interface for transaction signing parameters
*/
interface signTransactionProps {
unsignedTransaction: string;
address: string;
}
/**
* Sign a Stellar transaction using the connected wallet
* This function handles the signing process and returns the signed transaction
*
* @param unsignedTransaction - The XDR string of the unsigned transaction
* @param address - The wallet address that will sign the transaction
* @returns Promise<string> - The signed transaction XDR
*/
export const signTransaction = async ({
unsignedTransaction,
address,
}: signTransactionProps): Promise<string> => {
const { signedTxXdr } = await kit.signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
return signedTxXdr;
};"use client";
import {
createContext,
useContext,
useState,
useEffect,
ReactNode,
} from "react";
/**
* Type definition for the wallet context
* Contains wallet address, name, and functions to manage wallet state
*/
type WalletContextType = {
walletAddress: string | null;
walletName: string | null;
setWalletInfo: (address: string, name: string) => void;
clearWalletInfo: () => void;
};
/**
* Create the React context for wallet state management
*/
const WalletContext = createContext<WalletContextType | undefined>(undefined);
/**
* Wallet Provider component that wraps the application
* Manages wallet state and provides wallet information to child components
* Automatically loads saved wallet information from localStorage on initialization
*/
export const WalletProvider = ({ children }: { children: ReactNode }) => {
const [walletAddress, setWalletAddress] = useState<string | null>(null);
const [walletName, setWalletName] = useState<string | null>(null);
/**
* Load saved wallet information from localStorage when the component mounts
* This ensures the wallet state persists across browser sessions
*/
useEffect(() => {
const storedAddress = localStorage.getItem("walletAddress");
const storedName = localStorage.getItem("walletName");
if (storedAddress) setWalletAddress(storedAddress);
if (storedName) setWalletName(storedName);
}, []);
/**
* Set wallet information and save it to localStorage
* This function is called when a wallet is successfully connected
*
* @param address - The wallet's public address
* @param name - The name/identifier of the wallet (e.g., "Freighter", "Albedo")
*/
const setWalletInfo = (address: string, name: string) => {
setWalletAddress(address);
setWalletName(name);
localStorage.setItem("walletAddress", address);
localStorage.setItem("walletName", name);
};
/**
* Clear wallet information and remove it from localStorage
* This function is called when disconnecting a wallet
*/
const clearWalletInfo = () => {
setWalletAddress(null);
setWalletName(null);
localStorage.removeItem("walletAddress");
localStorage.removeItem("walletName");
};
return (
<WalletContext.Provider
value={{ walletAddress, walletName, setWalletInfo, clearWalletInfo }}
>
{children}
</WalletContext.Provider>
);
};
/**
* Custom hook to access the wallet context
* Provides wallet state and functions to components
* Throws an error if used outside of WalletProvider
*/
export const useWalletContext = () => {
const context = useContext(WalletContext);
if (!context) {
throw new Error("useWalletContext must be used within WalletProvider");
}
return context;
};import { kit } from "@/config/wallet-kit";
import { useWalletContext } from "@/providers/wallet.provider";
import { ISupportedWallet } from "@creit.tech/stellar-wallets-kit";
/**
* Custom hook that provides wallet connection and disconnection functionality
* Integrates with the Stellar Wallet Kit and manages wallet state through context
*/
export const useWallet = () => {
// Get wallet management functions from the context
const { setWalletInfo, clearWalletInfo } = useWalletContext();
/**
* Connect to a Stellar wallet using the Wallet Kit
* Opens a modal for wallet selection and handles the connection process
* Automatically sets wallet information in the context upon successful connection
*/
const connectWallet = async () => {
await kit.openModal({
modalTitle: "Connect to your favorite wallet",
onWalletSelected: async (option: ISupportedWallet) => {
// Set the selected wallet as the active wallet
kit.setWallet(option.id);
// Get the wallet address and name
const { address } = await kit.getAddress();
const { name } = option;
// Store wallet information in the context and localStorage
setWalletInfo(address, name);
},
});
};
/**
* Disconnect from the current wallet
* Clears wallet information from the context and localStorage
* Disconnects the wallet from the Stellar Wallet Kit
*/
const disconnectWallet = async () => {
await kit.disconnect();
clearWalletInfo();
};
/**
* Handle wallet connection with error handling
* Wraps the connectWallet function in a try-catch block for better error management
*/
const handleConnect = async () => {
try {
await connectWallet();
} catch (error) {
console.error("Error connecting wallet:", error);
// You can add additional error handling here, such as showing user notifications
}
};
/**
* Handle wallet disconnection with error handling
* Wraps the disconnectWallet function in a try-catch block for better error management
*/
const handleDisconnect = async () => {
try {
await disconnectWallet();
} catch (error) {
console.error("Error disconnecting wallet:", error);
// You can add additional error handling here, such as showing user notifications
}
};
return {
connectWallet,
disconnectWallet,
handleConnect,
handleDisconnect,
};
};import { WalletProvider } from "@/providers/wallet.provider";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<WalletProvider>
{children}
</WalletProvider>
</body>
</html>
);
}import { useWallet } from "@/hooks/wallet.hook";
import { useWalletContext } from "@/providers/wallet.provider";
/**
* Wallet connection/disconnection button component
* Shows different states based on wallet connection status
*/
export const WalletButton = () => {
const { handleConnect, handleDisconnect } = useWallet();
const { walletAddress, walletName } = useWalletContext();
// If wallet is connected, show disconnect option
if (walletAddress) {
return (
<div className="flex items-center gap-4">
<div className="text-sm">
<p className="font-medium">Connected: {walletName}</p>
<p className="text-gray-500">{walletAddress}</p>
</div>
<button
onClick={handleDisconnect}
className="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600"
>
Disconnect
</button>
</div>
);
}
// If wallet is not connected, show connect option
return (
<button
onClick={handleConnect}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
Connect Wallet
</button>
);
};Transaction hash
b0e61d4...f1cb2d29Returns the escrow object that was just saved/updated in the indexer and the success or failure of the response.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Collection of objects containing information on the balance of the requested addresses
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Array of contract IDs to query
[CB25FW...,CBHEQBV...]Is the escrow active
When set to true, the endpoint will verify each escrow’s data against the blockchain to ensure accuracy and integrity. Enabling this adds an extra security layer but may increase the response time slightly due to the additional validation step
Collection of data containing information from different scans requested by a signatory, role or contract ids.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
ID (address) that identifies the escrow contract
CAZ6UQX7...Position that identifies the milestone within the group of milestones in the escrow
1Address of the entity requiring the service
GCLIENT...XYZThis endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
ID (address) that identifies the escrow contract
ENG12345Entity that signs the transaction that deploys and initializes the escrow
GSIGN...XYZAmount to transfer to the escrow contract
100This endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
ID (address) that identifies the escrow contract
CAZ6UQX7...Address of the user defined to resolve disputes in an escrow
GDISPUTE...XYZPosition that identifies the milestone within the group of milestones in the escrow
1This endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
ID (address) that identifies the escrow contract
CAZ6UQX7...Position that identifies the milestone within the group of milestones in the escrow
1Entity that signs the transaction that deploys and initializes the escrow
GSIGN...XYZThis endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
ID (address) that identifies the escrow contract
CAZ6UQX7...Address of the user in charge of releasing the escrow funds to the receiver
GREL...XYZThis endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
ID (address) that identifies the escrow contract
CAZ6UQX7...Entity that signs the transaction that deploys and initializes the escrow
GSIGN...XYZThis endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
ID (address) that identifies the escrow contract
ENG12345Entity that signs the transaction that deploys and initializes the escrow
GSIGN...XYZAmount to transfer to the escrow contract
100This endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
ID (address) that identifies the escrow contract
CAZ6UQX7...Address of the user defined to resolve disputes in an escrow
GDISPUTE...XYZThis endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
ID (address) that identifies the escrow contract
CAZ6UQX7...milestone within the group of milestones in the escrow
1New value for the evidence property within the escrow milestone
EvidenceNew value for the status property within the escrow milestone
CompletedAddress of the entity providing the service
CompletedThis endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
ID (address) that identifies the escrow contract
CAZ6UQX7...milestone within the group of milestones in the escrow
1New value for the evidence property within the escrow milestone
EvidenceNew value for the status property within the escrow milestone
CompletedAddress of the entity providing the service
CompletedThis endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
The sign's hash. This come from the wallet
AAAAAgAAAAB...The transaction has been successfully sent to the Stellar network
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
ID (address) that identifies the escrow contract
CAZ6UQX7...Address of the user in charge of releasing the escrow funds to the receiver
GAPPROVER1234567890...Position that identifies the milestone within the group of milestones in the escrow
1This endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
ID (address) that identifies the escrow contract
CAZ6UQX7...Address of the user defined to resolve disputes in an escrow
GDISPUTE...XYZThis endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
ID (address) that identifies the escrow contract
CAZ6UQX7...Position that identifies the milestone within the group of milestones in the escrow
1Address of the entity requiring the service
GCLIENT...XYZThis endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
Entity that signs the transaction that deploys and initializes the escrow
GABC...XYZUnique identifier for the escrow
ENG12345Name of the escrow
Escrow TestText describing the function of the escrow
Escrow Test descriptionRoles that make up the escrow structure
Amount to be transferred upon completion of escrow milestones
1000Commission that the platform will receive when the escrow is completed
5Objectives to be completed to define the escrow as completed. (In this case it is not necessary to send the properties “approvedFlag” and “status” inside the objects of these milestones)
Information on the trustline that will manage the movement of funds in escrow
This endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
Entity that signs the transaction that deploys and initializes the escrow
GSIGN...XYZID (address) that identifies the escrow contract
CAZ6UQX7...Unique identifier for the escrow
ENG12345Name of the escrow
Test TitleText describing the function of the escrow
Escrow descriptionRoles that make up the escrow structure
Amount to be transferred upon completion of escrow milestones
1000Commission that the platform will receive when the escrow is completed
5Objectives to be completed to define the escrow as completed
Flags validating certain escrow life states
Flag indicating whether the escrow is active or not at the database level. Makes only a logical deletion, the escrow will continue to function at the blockchain level.
falseField used to identify the recipient's address in transactions through an intermediary account. This value is included as a memo in the transaction and allows the funds to be correctly routed to the wallet of the specified recipient
123456Information on the trustline that will manage the movement of funds in escrow
This endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
Address of the user who signed the transaction to create escrow
GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXRole in escrow
approverAddress of the user in the specified role
GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXStatus of the escrow
pendingType of the escrow
single_release | multi_releasePossible values: Engagement ID of the escrow
ENG-001Title of the escrow
Website redesignIs the escrow active
When set to true, the endpoint will verify each escrow’s data against the blockchain to ensure accuracy and integrity. Enabling this adds an extra security layer but may increase the response time slightly due to the additional validation step
Starting date range for filtering
2023-06-20 (YYYY-MM-DD)Minimum amount for filtering
100Maximum amount for filtering
1000Field to order the results by
createdAtExample: createdAt | updatedAt | amountPossible values: Direction to order the results
descExample: asc | descPossible values: Page number for pagination
1Number of items per page
8Example: 8Contract Id of the deployed escrow
CBHEQBV...Ending date range for filtering
2023-06-22 (YYYY-MM-DD)Collection of data containing information from different scans requested by a signatory, role or contract id.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Entity that signs the transaction that deploys and initializes the escrow
GABC...XYZUnique identifier for the escrow
ENG12345Name of the escrow
Escrow TestText describing the function of the escrow
Escrow Test descriptionRoles that make up the escrow structure
Commission that the platform will receive when the escrow is completed
5Objectives to be completed to define the escrow as completed. (In this case it is not necessary to send the properties “approvedFlag” and “status” inside the objects of these milestones)
Information on the trustline that will manage the movement of funds in escrow
This endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
Address of the user who signed the transaction to create escrow
GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXRole in escrow
approverAddress of the user in the specified role
GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXStatus of the escrow
pendingType of the escrow
single_release | multi_releasePossible values: Engagement ID of the escrow
ENG-001Title of the escrow
Website redesignIs the escrow active
When set to true, the endpoint will verify each escrow’s data against the blockchain to ensure accuracy and integrity. Enabling this adds an extra security layer but may increase the response time slightly due to the additional validation step
Starting date range for filtering
2023-06-20 (YYYY-MM-DD)Minimum amount for filtering
100Maximum amount for filtering
1000Field to order the results by
createdAtExample: createdAt | updatedAt | amountPossible values: Direction to order the results
descExample: asc | descPossible values: Page number for pagination
1Number of items per page
8Example: 8Contract Id of the deployed escrow
CBHEQBV...Ending date range for filtering
2023-06-22 (YYYY-MM-DD)Collection of data containing information from different scans requested by a signatory, role or contract id.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Entity that signs the transaction that deploys and initializes the escrow
GSIGN...XYZID (address) that identifies the escrow contract
CAZ6UQX7...Unique identifier for the escrow
ENG12345Name of the escrow
Test TitleText describing the function of the escrow
Escrow descriptionRoles that make up the escrow structure
Amount to be transferred upon completion of escrow milestones
1000Commission that the platform will receive when the escrow is completed
5Objectives to be completed to define the escrow as completed
Flags validating certain escrow life states
Flag indicating whether the escrow is active or not at the database level. Makes only a logical deletion, the escrow will continue to function at the blockchain level.
falseField used to identify the recipient's address in transactions through an intermediary account. This value is included as a memo in the transaction and allows the funds to be correctly routed to the wallet of the specified recipient
123456Information on the trustline that will manage the movement of funds in escrow
This endpoint returns an unsigned transaction in XDR format. This XDR is then used to sign the transaction using the “/helper/send-transaction” endpoint.
Bad request
No content
Unauthorized access
No content
Too Many Requests
No content
Possible errors:
PUT /indexer/update-from-txhash HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 31
{
"txHash": "b0e61d4...f1cb2d29"
}{
"status": "SUCCESS",
"message": "Escrow saved successfully / The escrow has been correctly indexed in our database.",
"savedEscrow": {
"contractId": "CB25FW....",
"signer": "GBPUA....",
"type": "multi-release",
"engagementId": "ENG-003",
"title": "Title of the Escrow",
"description": "Description of the Escrow",
"milestones": [
{
"description": "Initial payment",
"amount": 2,
"status": "pending",
"flags": {
"disputed": false,
"released": false,
"resolved": false,
"approved": false
}
},
{
"description": "Final payment",
"amount": 5,
"status": "pending",
"flags": {
"disputed": false,
"released": false,
"resolved": false,
"approved": false
}
}
],
"platformFee": 5,
"receiverMemo": 0,
"roles": {
"approver": "GBPUACN....",
"serviceProvider": "GA2RRI....",
"platformAddress": "GBPA2LO....",
"releaseSigner": "GCPZUO....",
"disputeResolver": "GDBMRV...",
"receiver": "GA2RRI...",
"issuer": "GBPUAC..."
},
"trustline": {
"address": "CBIELT...",
"name": "USDC"
},
"isActive": true,
"updatedAt": {
"_seconds": 1750698602,
"_nanoseconds": 356000000
},
"createdAt": {
"_seconds": 1750698602,
"_nanoseconds": 356000000
},
"balance": 0
}
}GET /helper/get-multiple-escrow-balance?addresses=undefined HTTP/1.1
Accept: */*
[
{
"address": "GAWVVSA..",
"balance": 30
},
{
"address": "GAWVCG3..",
"balance": 10
}
]GET /helper/get-escrow-by-contract-ids?contractIds=[CB25FW...%2CCBHEQBV...] HTTP/1.1
Accept: */*
[
{
"contractId": "CB25FW....",
"signer": "GBPUA....",
"type": "multi-release",
"engagementId": "ENG-003",
"title": "Title of the Escrow",
"description": "Description of the Escrow",
"milestones": [
{
"description": "Initial payment",
"amount": 2,
"status": "pending",
"flags": {
"disputed": false,
"released": false,
"resolved": false,
"approved": false
}
},
{
"description": "Final payment",
"amount": 5,
"status": "pending",
"flags": {
"disputed": false,
"released": false,
"resolved": false,
"approved": false
}
}
],
"platformFee": 5,
"receiverMemo": 0,
"roles": {
"approver": "GBPUACN....",
"serviceProvider": "GA2RRI....",
"platformAddress": "GBPA2LO....",
"releaseSigner": "GCPZUO....",
"disputeResolver": "GDBMRV...",
"receiver": "GA2RRI...",
"issuer": "GBPUAC..."
},
"trustline": {
"address": "CBIELT...",
"name": "USDC"
},
"isActive": true,
"updatedAt": {
"_seconds": 1750698602,
"_nanoseconds": 356000000
},
"createdAt": {
"_seconds": 1750698602,
"_nanoseconds": 356000000
},
"balance": 0
},
{
"contractId": "CF35XW....",
"signer": "GBPUA....",
"type": "single-release",
"engagementId": "ENG-003",
"title": "Title of the Escrow",
"description": "Description of the Escrow",
"milestones": [
{
"description": "Initial payment",
"amount": 5,
"status": "pending",
"flags": {
"disputed": false,
"released": false,
"resolved": false,
"approved": false
}
},
{
"description": "Final payment",
"amount": 3,
"status": "pending",
"flags": {
"disputed": false,
"released": false,
"resolved": false,
"approved": false
}
}
],
"platformFee": 3,
"receiverMemo": 0,
"roles": {
"approver": "GBPUACN....",
"serviceProvider": "GA2RRI....",
"platformAddress": "GBPA2LO....",
"releaseSigner": "GCPZUO....",
"disputeResolver": "GDBMRV...",
"receiver": "GA2RRI...",
"issuer": "GBPUAC..."
},
"trustline": {
"address": "CBIELT...",
"name": "USDC"
},
"isActive": true,
"updatedAt": {
"_seconds": 1750698602,
"_nanoseconds": 356000000
},
"createdAt": {
"_seconds": 1750698602,
"_nanoseconds": 356000000
},
"balance": 3
}
]POST /escrow/single-release/approve-milestone HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 85
{
"contractId": "CAZ6UQX7...",
"milestoneIndex": "1",
"approver": "GAPPROVER1234567890..."
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /escrow/multi-release/fund-escrow HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 74
{
"contractId": "CAZ6UQX7...",
"signer": "GAPPROVER1234567890...",
"amount": 10
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /escrow/multi-release/resolve-milestone-dispute HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 210
{
"contractId": "CAZ6UQX7...",
"disputeResolver": "GAPPROVER1234567890...",
"milestoneIndex": "1",
"distributions": [
{
"address": "GAPPROVER1234567890...",
"amount": 300
},
{
"address": "GRECEIVER1234567890...",
"amount": 700
}
]
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /escrow/multi-release/dispute-milestone HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 83
{
"contractId": "CAZ6UQX7...",
"milestoneIndex": "1",
"signer": "GAPPROVER1234567890..."
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /escrow/single-release/release-funds HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 69
{
"contractId": "CAZ6UQX7...",
"releaseSigner": "GAPPROVER1234567890..."
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /escrow/single-release/dispute-escrow HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 62
{
"contractId": "CAZ6UQX7...",
"signer": "GAPPROVER1234567890..."
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /escrow/single-release/fund-escrow HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 74
{
"contractId": "CAZ6UQX7...",
"signer": "GAPPROVER1234567890...",
"amount": 10
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /escrow/multi-release/withdraw-remaining-funds HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 188
{
"contractId": "CAZ6UQX7...",
"disputeResolver": "GDISPUTE1234567890...",
"distributions": [
{
"address": "GAPPROVER1234567890...",
"amount": 150
},
{
"address": "GRECEIVER1234567890...",
"amount": 850
}
]
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /escrow/multi-release/change-milestone-status HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 177
{
"contractId": "CAZ6UQX7...",
"milestoneIndex": "1",
"newEvidence": "Any evidence that the milestone is completed",
"newStatus": "Completed",
"serviceProvider": "GAPPROVER1234567890..."
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /escrow/single-release/change-milestone-status HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 177
{
"contractId": "CAZ6UQX7...",
"milestoneIndex": "1",
"newEvidence": "Any evidence that the milestone is completed",
"newStatus": "Completed",
"serviceProvider": "GAPPROVER1234567890..."
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /helper/send-transaction HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 30
{
"signedXdr": "AAAAAgAAAAB..."
}{
"status": "SUCCESS",
"message": "The transaction has been successfully sent to the Stellar network.",
"contractId": "CAATN5D...",
"escrow": {
"amount": 50,
"roles": {
"approver": "GAWVVSA...",
"serviceProvider": "GAWVVSA6...",
"disputeResolver": "GAWVVSA...",
"receiver": "GAWVVSA...",
"platformAddress": "GAWVVSA...",
"releaseSigner": "GAWVVSA..."
},
"flags": {
"disputed": false,
"released": false,
"resolved": false
},
"description": "This is a sample TW escrow for testing purposes",
"engagementId": "ENG12345",
"milestones": [
{
"approved": false,
"description": "Initial milestone",
"evidence": "",
"status": "pending"
},
{
"approved": false,
"description": "Second milestone",
"evidence": "",
"status": "pending"
}
],
"platformFee": 5,
"title": "Sample TW Escrow",
"trustline": {
"address": "CBIELTK...",
"name": "USDC"
},
"receiverMemo": 90909090
}
}POST /escrow/multi-release/release-milestone-funds HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 91
{
"contractId": "CAZ6UQX7...",
"releaseSigner": "GAPPPROVER1234567890...",
"milestoneIndex": "1"
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /escrow/single-release/resolve-dispute HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 188
{
"contractId": "CAZ6UQX7...",
"disputeResolver": "GAPPROVER1234567890...",
"distributions": [
{
"address": "GAPPROVER1234567890...",
"amount": 20
},
{
"address": "GRECIPIENT1234567890...",
"amount": 30
}
]
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /escrow/multi-release/approve-milestone HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 85
{
"contractId": "CAZ6UQX7...",
"milestoneIndex": "1",
"approver": "GAPPROVER1234567890..."
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /deployer/single-release HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 603
{
"signer": "GAPPROVER1234567890...",
"engagementId": "ENG12345",
"title": "Project Title",
"description": "This is a detailed description of the project.",
"roles": {
"approver": "GAPPROVER1234567890...",
"serviceProvider": "GAPPROVER1234567890...",
"platformAddress": "GAPPROVER1234567890...",
"releaseSigner": "GAPPROVER1234567890...",
"disputeResolver": "GAPPROVER1234567890...",
"receiver": "GAPPROVER1234567890..."
},
"amount": 1000,
"platformFee": 50,
"milestones": [
{
"description": "Initial phase of the project"
},
{
"description": "Completion of design work"
}
],
"trusline": {
"symbol": "USDC",
"address": "GBBD47IF6LWK7P7MDEVSC..."
}
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}PUT /escrow/multi-release/update-escrow HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 878
{
"signer": "GAPPROVER1234567890...",
"contractId": "CAZ6UQX7...",
"isActive": true,
"escrow": {
"engagementId": "ENG12345",
"title": "Project Title",
"description": "This is a detailed description of the project.",
"roles": {
"approver": "GAPPROVER1234567890...",
"serviceProvider": "GAPPROVER1234567890...",
"platformAddress": "GAPPROVER1234567890...",
"releaseSigner": "GAPPROVER1234567890...",
"disputeResolver": "GAPPROVER1234567890..."
},
"platformFee": 1,
"milestones": [
{
"description": "test1",
"status": "pending",
"evidence": "Any evidence that the milestone is completed",
"amount": 1000,
"receiver": "GAPPROVER1234567890..."
},
{
"description": "test2",
"status": "pending",
"evidence": "Any evidence that the milestone is completed",
"amount": 1000,
"receiver": "GAPPROVER1234567890..."
}
],
"flags": {
"disputed": false,
"released": false,
"resolved": false,
"approved": false
},
"trustline": {
"address": "GAPPROVER1234567890..."
}
}
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}POST /deployer/multi-release HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 648
{
"signer": "GAPPROVER1234567890...",
"engagementId": "ENG12345",
"title": "Project Title",
"description": "This is a detailed description of the project.",
"roles": {
"approver": "GAPPROVER1234567890...",
"serviceProvider": "GAPPROVER1234567890...",
"platformAddress": "GAPPROVER1234567890...",
"releaseSigner": "GAPPROVER1234567890...",
"disputeResolver": "GAPPROVER1234567890..."
},
"platformFee": 50,
"milestones": [
{
"description": "Initial phase of the project",
"amount": 5,
"receiver": "GAPPROVER1234567890..."
},
{
"description": "Completion of design work",
"amount": 5,
"receiver": "GAPPROVER1234567890..."
}
],
"trustline": {
"symbol": "USDC",
"address": "GBBD47IF6LWK7P7MDEVSC..."
}
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}PUT /escrow/single-release/update-escrow HTTP/1.1
Content-Type: application/json
Accept: */*
Content-Length: 846
{
"signer": "GAPPROVER1234567890...",
"contractId": "CAZ6UQX7...",
"isActive": true,
"escrow": {
"signer": "GAPPROVER1234567890...",
"engagementId": "ENG12345",
"title": "Project Title",
"description": "This is a detailed description of the project.",
"roles": {
"approver": "GAPPROVER1234567890...",
"serviceProvider": "GAPPROVER1234567890...",
"platformAddress": "GAPPROVER1234567890...",
"releaseSigner": "GAPPROVER1234567890...",
"disputeResolver": "GAPPROVER1234567890...",
"receiver": "GAPPROVER1234567890..."
},
"amount": 1000,
"platformFee": 50,
"milestones": [
{
"description": "test1",
"status": "pending",
"evidence": "Any evidence that the milestone is completed"
},
{
"description": "test2",
"status": "pending",
"evidence": "Any evidence that the milestone is completed"
}
],
"flags": {
"disputed": false,
"released": false,
"resolved": false
},
"trustline": {
"address": "GAPPROVER1234567890..."
}
}
}{
"status": "SUCCESS",
"unsignedTransaction": "AAAAAgAAAAAtWsgedQ...."
}[
{
"contractId": "CB25FW....",
"signer": "GBPUA....",
"type": "multi-release",
"engagementId": "ENG-003",
"title": "Title of the Escrow",
"description": "Description of the Escrow",
"milestones": [
{
"description": "Initial payment",
"amount": 2,
"status": "pending",
"flags": {
"disputed": false,
"released": false,
"resolved": false,
"approved": false
}
},
{
"description": "Final payment",
"amount": 5,
"status": "pending",
"flags": {
"disputed": false,
"released": false,
"resolved": false,
"approved": false
}
}
],
"platformFee": 5,
"receiverMemo": 0,
"roles": {
"approver": "GBPUACN....",
"serviceProvider": "GA2RRI....",
"platformAddress": "GBPA2LO....",
"releaseSigner": "GCPZUO....",
"disputeResolver": "GDBMRV...",
"receiver": "GA2RRI...",
"issuer": "GBPUAC..."
},
"trustline": {
"address": "CBIELT...",
"name": "USDC"
},
"isActive": true,
"updatedAt": {
"_seconds": 1750698602,
"_nanoseconds": 356000000
},
"createdAt": {
"_seconds": 1750698602,
"_nanoseconds": 356000000
},
"balance": 0
}
]GET /helper/get-escrows-by-signer HTTP/1.1
Accept: */*
[
{
"contractId": "CB25FW....",
"signer": "GBPUA....",
"type": "multi-release",
"engagementId": "ENG-003",
"title": "Title of the Escrow",
"description": "Description of the Escrow",
"milestones": [
{
"description": "Initial payment",
"amount": 2,
"status": "pending",
"flags": {
"disputed": false,
"released": false,
"resolved": false,
"approved": false
}
},
{
"description": "Final payment",
"amount": 5,
"status": "pending",
"flags": {
"disputed": false,
"released": false,
"resolved": false,
"approved": false
}
}
],
"platformFee": 5,
"receiverMemo": 0,
"roles": {
"approver": "GBPUACN....",
"serviceProvider": "GA2RRI....",
"platformAddress": "GBPA2LO....",
"releaseSigner": "GCPZUO....",
"disputeResolver": "GDBMRV...",
"receiver": "GA2RRI...",
"issuer": "GBPUAC..."
},
"trustline": {
"address": "CBIELT...",
"name": "USDC"
},
"isActive": true,
"updatedAt": {
"_seconds": 1750698602,
"_nanoseconds": 356000000
},
"createdAt": {
"_seconds": 1750698602,
"_nanoseconds": 356000000
},
"balance": 0
}
]GET /helper/get-escrows-by-role HTTP/1.1
Accept: */*



