Skip to content

Latest commit

 

History

History
670 lines (544 loc) · 17.2 KB

File metadata and controls

670 lines (544 loc) · 17.2 KB

Code Examples - Complete Integration Scenarios

Table of Contents

  1. Freelance Marketplace
  2. DAO Grant Program
  3. Security Deposit (Rental)
  4. Crowdfunding Platform
  5. E-commerce Escrow
  6. React Component Examples

1. Freelance Marketplace

Complete flow: Client hires freelancer → Escrow funded → Work delivered → Payment released

Scenario

  • Client needs a website
  • Freelancer builds it in 2 phases
  • Single-release escrow (one payout after both milestones)
  • Platform takes 2% fee

Step 1: Create Escrow

import { TrustlessWorkSDK } from '@trustless-work/sdk';

const sdk = new TrustlessWorkSDK({
  apiKey: process.env.TRUSTLESS_API_KEY,
  network: 'mainnet'
});

async function createFreelanceEscrow() {
  const escrow = await sdk.escrow.createSingleRelease({
    engagementId: `project-${Date.now()}`,
    title: "Marketing Website Development",
    description: "5-page marketing website with responsive design and CMS integration",

    roles: {
      approver: "GCLIENT_PUBLIC_KEY",           // Client approves
      serviceProvider: "GFREELANCER_PUBLIC_KEY", // Freelancer delivers
      releaseSigner: "GPLATFORM_PUBLIC_KEY",     // Platform releases
      platformAddress: "GPLATFORM_PUBLIC_KEY",   // Platform receives fee
      disputeResolver: "GPLATFORM_PUBLIC_KEY",   // Platform resolves disputes
      receiver: "GFREELANCER_PUBLIC_KEY"         // Freelancer receives payment
    },

    amount: 2000, // $2,000 USDC
    platformFee: 2.0, // 2% platform fee

    milestones: [
      {
        description: "Homepage + 2 pages designed and approved",
        status: "Not Started",
        approved: false
      },
      {
        description: "All pages developed, CMS integrated, site deployed",
        status: "Not Started",
        approved: false
      }
    ],

    trustline: {
      address: "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5", // USDC
      code: "USDC"
    }
  });

  console.log("Escrow created:", escrow.contractId);
  console.log("View at:", `https://viewer.trustlesswork.com/${escrow.contractId}`);

  return escrow;
}

Step 2: Fund Escrow (Client)

async function fundEscrow(escrowId: string, clientWallet: string) {
  const result = await sdk.escrow.fund(escrowId, {
    amount: 2000,
    depositorAddress: clientWallet
  });

  console.log("Funding transaction:", result.transactionHash);
  console.log("New balance:", result.newBalance);

  return result;
}

Step 3: Update Milestones (Freelancer)

async function markMilestoneComplete(
  escrowId: string,
  milestoneIndex: number,
  deliverableUrl: string
) {
  const result = await sdk.escrow.updateMilestone(escrowId, milestoneIndex, {
    status: "Complete",
    evidence: {
      url: deliverableUrl,
      description: "Design files and live preview link",
      timestamp: new Date().toISOString()
    }
  });

  console.log(`Milestone ${milestoneIndex} marked complete`);
  return result;
}

// Freelancer marks both milestones
await markMilestoneComplete(escrowId, 0, "https://figma.com/design-link");
await markMilestoneComplete(escrowId, 1, "https://website.com");

Step 4: Approve Work (Client)

async function approveMilestones(escrowId: string) {
  const result = await sdk.escrow.approve(escrowId, {
    milestones: [0, 1] // Approve both milestones
  });

  console.log("Milestones approved:", result.approvedMilestones);
  console.log("Ready for release:", result.readyForRelease);

  return result;
}

Step 5: Release Payment (Platform)

async function releasePayment(escrowId: string) {
  const result = await sdk.escrow.release(escrowId, {
    releaseAll: true
  });

  console.log("Payment released!");
  console.log("Amount to freelancer:", result.amountReleased); // $1,954
  console.log("Platform fee:", result.platformFee);              // $40
  console.log("Protocol fee:", result.protocolFee);              // $6
  console.log("Transaction:", result.transactionHash);

  return result;
}

Complete Workflow

async function runFreelanceWorkflow() {
  // 1. Create escrow
  const escrow = await createFreelanceEscrow();

  // 2. Client funds it
  await fundEscrow(escrow.contractId, "GCLIENT_WALLET");

  // 3. Freelancer delivers work
  await markMilestoneComplete(escrow.contractId, 0, "https://figma.com/...");
  await markMilestoneComplete(escrow.contractId, 1, "https://live-site.com");

  // 4. Client approves
  await approveMilestones(escrow.contractId);

  // 5. Platform releases payment
  await releasePayment(escrow.contractId);

  console.log("✅ Workflow complete!");
}

2. DAO Grant Program

Multi-release escrow with milestone-based funding

Scenario

  • DAO awards $10,000 research grant
  • 3 milestones, each with its own payout
  • Payments released incrementally

Create Multi-Release Escrow

async function createDaoGrant() {
  const escrow = await sdk.escrow.createMultiRelease({
    engagementId: "grant-season-3-project-42",
    title: "DeFi Research Grant - Q1 2026",
    description: "Research on cross-chain liquidity protocols",

    roles: {
      approver: "GDAO_MULTISIG",
      serviceProvider: "GRESEARCHER_WALLET",
      releaseSigner: "GDAO_TREASURY",
      platformAddress: "GGRANT_PLATFORM",
      disputeResolver: "GDAO_MULTISIG"
    },

    platformFee: 0, // No platform fee for grants

    milestones: [
      {
        description: "Literature review and methodology (30 days)",
        amount: 3000,
        status: "Not Started",
        flags: {
          approved: false,
          released: false,
          disputed: false,
          resolved: false
        },
        receiver: "GRESEARCHER_WALLET"
      },
      {
        description: "Data collection and analysis (60 days)",
        amount: 4000,
        status: "Not Started",
        flags: {
          approved: false,
          released: false,
          disputed: false,
          resolved: false
        },
        receiver: "GRESEARCHER_WALLET"
      },
      {
        description: "Final report and presentation (30 days)",
        amount: 3000,
        status: "Not Started",
        flags: {
          approved: false,
          released: false,
          disputed: false,
          resolved: false
        },
        receiver: "GRESEARCHER_WALLET"
      }
    ],

    trustline: {
      address: "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",
      code: "USDC"
    }
  });

  return escrow;
}

Release Milestone-by-Milestone

async function releaseMilestone(escrowId: string, milestoneId: number) {
  // DAO votes and approves milestone
  await sdk.escrow.approve(escrowId, { milestoneId });

  // Treasury releases that milestone's funds
  const result = await sdk.escrow.release(escrowId, { milestoneId });

  console.log(`Milestone ${milestoneId} released: $${result.amountReleased}`);
  return result;
}

// Over time, as each milestone completes:
await releaseMilestone(escrowId, 0); // $3,000 released
// ... 30 days later ...
await releaseMilestone(escrowId, 1); // $4,000 released
// ... 60 days later ...
await releaseMilestone(escrowId, 2); // $3,000 released

3. Security Deposit (Rental)

Airbnb-style deposit that's returned after checkout

Scenario

  • Guest books rental for $200/night
  • $500 security deposit held in escrow
  • After checkout, host approves → deposit returned to guest

Create Deposit Escrow

async function createSecurityDeposit() {
  const escrow = await sdk.escrow.createSingleRelease({
    engagementId: `booking-${bookingId}`,
    title: "Security Deposit - Mountain Cabin",
    description: "Refundable security deposit for 3-night stay (March 15-18, 2026)",

    roles: {
      approver: "GHOST_WALLET",           // Host approves checkout
      serviceProvider: "GGUEST_WALLET",   // Guest is "provider" of clean checkout
      releaseSigner: "GPLATFORM_WALLET",
      platformAddress: "GPLATFORM_WALLET",
      disputeResolver: "GPLATFORM_WALLET",
      receiver: "GGUEST_WALLET"           // Deposit returned to guest
    },

    amount: 500, // $500 USDC deposit
    platformFee: 0, // No fee on deposits

    milestones: [
      {
        description: "Property checkout completed without damage",
        status: "Pending checkout",
        approved: false
      }
    ],

    trustline: {
      address: "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",
      code: "USDC"
    }
  });

  return escrow;
}

Checkout Flow

async function processCheckout(escrowId: string) {
  // Guest marks checkout complete
  await sdk.escrow.updateMilestone(escrowId, 0, {
    status: "Checkout complete",
    evidence: {
      description: "Keys returned, property cleaned",
      timestamp: new Date().toISOString()
    }
  });

  // Host inspects and approves
  await sdk.escrow.approve(escrowId, { milestones: [0] });

  // Platform releases deposit back to guest
  const result = await sdk.escrow.release(escrowId, { releaseAll: true });

  console.log(`Deposit of $${result.amountReleased} returned to guest`);
}

Damage Dispute Flow

async function handleDamageDispute(escrowId: string) {
  // Host raises dispute
  await sdk.escrow.dispute(escrowId, {
    reason: "Broken window, cleaning required",
    evidence: "Photos of damage, repair invoice: $300",
    requestedAction: "$300 to host, $200 refund to guest"
  });

  // Platform resolves: split deposit
  await sdk.escrow.resolveDispute(escrowId, {
    action: "split",
    distributions: [
      { recipient: "GHOST_WALLET", percentage: 60 },  // $300
      { recipient: "GGUEST_WALLET", percentage: 40 }  // $200
    ]
  });
}

4. Crowdfunding Platform

Pre-orders with conditional payout

Scenario

  • Creator launches product crowdfunding
  • Backers fund escrow
  • Milestones: Prototype → Manufacturing → Shipping
  • Multi-release to creator as milestones hit

Create Crowdfunding Escrow

async function createCrowdfundingEscrow() {
  const escrow = await sdk.escrow.createMultiRelease({
    engagementId: "campaign-gadget-2026",
    title: "Smart Home Gadget - Pre-Orders",
    description: "Manufacturing and delivery of 500 units",

    roles: {
      approver: "GPLATFORM_WALLET",        // Platform verifies milestones
      serviceProvider: "GCREATOR_WALLET",   // Creator delivers
      releaseSigner: "GPLATFORM_WALLET",
      platformAddress: "GPLATFORM_WALLET",
      disputeResolver: "GPLATFORM_WALLET"
    },

    platformFee: 5.0, // 5% platform fee

    milestones: [
      {
        description: "Working prototype demonstrated",
        amount: 15000,
        receiver: "GCREATOR_WALLET"
      },
      {
        description: "500 units manufactured",
        amount: 25000,
        receiver: "GCREATOR_WALLET"
      },
      {
        description: "All units shipped to backers",
        amount: 10000,
        receiver: "GCREATOR_WALLET"
      }
    ],

    trustline: {
      address: "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",
      code: "USDC"
    }
  });

  return escrow;
}

Multiple Backers Fund

async function collectBackerFunds(escrowId: string, backers: Array<{wallet: string, amount: number}>) {
  for (const backer of backers) {
    await sdk.escrow.fund(escrowId, {
      amount: backer.amount,
      depositorAddress: backer.wallet
    });
    console.log(`Backer ${backer.wallet} pledged $${backer.amount}`);
  }
}

// Example: 10 backers each pledge $5,000
const backers = [
  { wallet: "GBACKER1...", amount: 5000 },
  { wallet: "GBACKER2...", amount: 5000 },
  // ... 8 more backers
];
await collectBackerFunds(escrowId, backers);

5. E-commerce Escrow

Buyer protection for high-value purchases

Create Purchase Escrow

async function createPurchaseEscrow(orderId: string, amount: number) {
  return await sdk.escrow.createSingleRelease({
    engagementId: `order-${orderId}`,
    title: "Electronics Purchase - MacBook Pro",
    description: "New MacBook Pro 16-inch with buyer protection",

    roles: {
      approver: "GBUYER_WALLET",          // Buyer approves receipt
      serviceProvider: "GSELLER_WALLET",   // Seller ships
      releaseSigner: "GMARKETPLACE_WALLET",
      platformAddress: "GMARKETPLACE_WALLET",
      disputeResolver: "GMARKETPLACE_WALLET",
      receiver: "GSELLER_WALLET"
    },

    amount,
    platformFee: 3.0, // 3% marketplace fee

    milestones: [
      {
        description: "Item shipped with tracking",
        status: "Pending shipment",
        approved: false
      },
      {
        description: "Item received and inspected by buyer",
        status: "Awaiting delivery",
        approved: false
      }
    ],

    trustline: {
      address: "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",
      code: "USDC"
    }
  });
}

Shipping Flow

async function handleShipping(escrowId: string, trackingNumber: string) {
  // Seller marks as shipped
  await sdk.escrow.updateMilestone(escrowId, 0, {
    status: "Shipped",
    evidence: {
      url: `https://tracking.com/${trackingNumber}`,
      description: `Tracking: ${trackingNumber}`,
      timestamp: new Date().toISOString()
    }
  });

  // Buyer receives and confirms
  await sdk.escrow.updateMilestone(escrowId, 1, {
    status: "Received and inspected - all good",
    evidence: {
      description: "Item matches description, no damage"
    }
  });

  // Buyer approves
  await sdk.escrow.approve(escrowId, { milestones: [0, 1] });

  // Marketplace releases payment to seller
  await sdk.escrow.release(escrowId, { releaseAll: true });
}

6. React Component Examples

Create Escrow Form

import { useCreateEscrow } from '@trustless-work/react-sdk';

function CreateEscrowForm() {
  const { createEscrow, loading, error } = useCreateEscrow();
  const [formData, setFormData] = useState({
    title: '',
    amount: 0,
    clientAddress: '',
    freelancerAddress: ''
  });

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    const escrow = await createEscrow({
      type: 'single-release',
      title: formData.title,
      amount: formData.amount,
      roles: {
        approver: formData.clientAddress,
        serviceProvider: formData.freelancerAddress,
        releaseSigner: YOUR_PLATFORM_ADDRESS,
        platformAddress: YOUR_PLATFORM_ADDRESS,
        disputeResolver: YOUR_PLATFORM_ADDRESS,
        receiver: formData.freelancerAddress
      },
      milestones: [
        { description: 'Work complete', status: 'Pending', approved: false }
      ],
      platformFee: 2.0,
      trustline: {
        address: 'GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5',
        code: 'USDC'
      }
    });

    console.log('Escrow created:', escrow.contractId);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        placeholder="Project Title"
        value={formData.title}
        onChange={(e) => setFormData({...formData, title: e.target.value})}
      />
      <input
        type="number"
        placeholder="Amount (USDC)"
        value={formData.amount}
        onChange={(e) => setFormData({...formData, amount: +e.target.value})}
      />
      <button type="submit" disabled={loading}>
        {loading ? 'Creating...' : 'Create Escrow'}
      </button>
      {error && <p>Error: {error.message}</p>}
    </form>
  );
}

Fund Escrow Component

import { useFundEscrow } from '@trustless-work/react-sdk';
import { useWallet } from '@stellar/wallet-sdk'; // Or Freighter

function FundEscrowButton({ escrowId, amount }: { escrowId: string, amount: number }) {
  const { fundEscrow, loading } = useFundEscrow();
  const { publicKey, signTransaction } = useWallet();

  const handleFund = async () => {
    try {
      const result = await fundEscrow(escrowId, {
        amount,
        depositorAddress: publicKey,
        signTransaction // Wallet signing function
      });

      alert(`Funded! TX: ${result.transactionHash}`);
    } catch (err) {
      console.error('Funding failed:', err);
    }
  };

  return (
    <button onClick={handleFund} disabled={loading}>
      {loading ? 'Funding...' : `Fund ${amount} USDC`}
    </button>
  );
}

Escrow Status Dashboard

import { useEscrow } from '@trustless-work/react-sdk';

function EscrowDashboard({ escrowId }: { escrowId: string }) {
  const { escrow, loading, refresh } = useEscrow(escrowId);

  if (loading) return <div>Loading...</div>;
  if (!escrow) return <div>Escrow not found</div>;

  return (
    <div>
      <h2>{escrow.title}</h2>
      <p>Balance: ${escrow.balance} USDC</p>
      <p>Status: {escrow.flags.released ? 'Released' : 'Active'}</p>

      <h3>Milestones</h3>
      {escrow.milestones.map((milestone, i) => (
        <div key={i}>
          <strong>{milestone.description}</strong>
          <span> - {milestone.status}</span>
          {milestone.approved && <span> ✅ Approved</span>}
        </div>
      ))}

      <button onClick={refresh}>Refresh</button>
    </div>
  );
}

Next Steps