Building a Web3 Peer to Peer Payments App

Conceptual Overview

By combining the power of many of Wyre's APIs, our partners can build apps that allow end users to send and receive funds similar to many of the popular peer-to-peer payments apps that have become household names.

With Wyre's Users API, we allow partners and developers to safely and compliantly KYC and onboard their users as well as store funds for users that fulfill KYC requirements.

Wyre's Payment Method API allows bank accounts to be attached to every user that passes KYC.

Wyre's Transfers API enables fiat funds onboarding via various banking methods as well as sending payments to other users or exchanging currencies between users or within the same user without a blockchain network fee.

Step 1: Create a Wyre Account and Generate Keys

Go to Set Up Your Account to learn how to generate keys and start building on TestWyre!

Step 2: Create a User

Create a User with First Name, Last Name, Date of Birth, Cell Phone Number, Email, and Redidential Address.

{
    "fields": {
        "firstName": "Alberta",
        "lastName": "Charleson",
        "legalName": "Alberta Charleson",
        "dateOfBirth": "1975-03-06",
        "cellphoneNumber": "+1112224444",
        "email": "[email protected]m",
        "residenceAddress": {
            "street1": "2992 Cameron Road",
            "city": "Malakoff",
            "state": "CA",
            "postalCode": "14236",
            "country": "US"
        }
    },
    "blockchains": [
        "ALL"
    ]
}
{
    "id": "US_39CUCTGTVBB",
    "status": "APPROVED",
    "partnerId": "PT_UUEJLH74VEN",
    "type": "INDIVIDUAL",
    "createdAt": 1648361213033,
    "depositAddresses": {
        "BTC": "miFkpeaFfrLG9A7owsHWQnj8iXitsdB4Gk",
        "MATIC": "0xf40501f440eb0c596ee053f88bd43ba9ae136b56",
        "AVAX": "0xe494a6d8d10f23630ba9f0b99bf455e9d4951abc",
        "ETH": "0x6c70a5acb186d4c447719d24e31a2a80f1539dc1",
        "XLM": "GD7WXI7AOAK2CIPZVBEFYLS2NQZI2J4WN4HFYQQ4A2OMFVWGWAL3IW7K:V9PMQ8EYEWC",
        "AVAXC": "0xf01724bb979df8ff888805809a014d93087f8d24"
    },
    "totalBalances": {},
    "availableBalances": {},
    "fields": {
        "firstName": {
            "value": "Alberta",
            "error": null,
            "status": "SUBMITTED"
        },
        "lastName": {
            "value": "Charleson",
            "error": null,
            "status": "SUBMITTED"
        },
        "dateOfBirth": {
            "value": "1975-03-06",
            "error": null,
            "status": "SUBMITTED"
        },
        "residenceAddress": {
            "value": {
                "street1": "2992 Cameron Road",
                "city": "Malakoff",
                "state": "NY",
                "postalCode": "14236",
                "country": "US"
            },
            "error": null,
            "status": "SUBMITTED"
        }
    }
}

Step 3: Connect Bank Account

By Masquerading as the user, we can attach a payment method using our Create Payment Method API via two methods:

The first method is creating a Plaid processor token and then passing it to Wyre via the API.

#first create processor token via plaid

curl --location --request POST 'https://sandbox.plaid.com/processor/token/create' \
--header 'Content-Type: application/json' \
--data-raw '{
    "client_id": "60f5d817da3e5300110xxxx",
    "secret": "a0adfa408349072862bbb7xxxxxx",
    "access_token": "access-sandbox-bd8a8917-84bd-4d1a-b231-671ecf3fb850",
    "account_id": "DmzZEm5kA7Hl3yepvXN4hQ4lj6yrGXhXVPNKk",
    "processor": "wyre"
  }'
  
  #response:
  {
    "processor_token": "processor-sandbox-af653618-f9e4-41ad-a567-03109952b2b3",
    "request_id": "GssgMK1wnpPBeiK"
}

#Take the processor token from the response and send it to create payment method API
#masquerading as the User

curl --location --request POST 'https://api.testwyre.com/v2/paymentMethods?masqueradeAs=user:US_39CUCTGTVBB' \
--header 'Authorization: Bearer SK-86Z8FYFB-UTA2RDCN-HCZBFT2V-XXX' \
--header 'Content-Type: application/json' \
--data-raw '{
     "plaidProcessorToken": "processor-sandbox-af653618-f9e4-41ad-a567-03109952b2b3",
     "paymentMethodType": "LOCAL_TRANSFER",
     "country": "US"
}'

#response:
{
    "id": "PA_DZ9WJXQEPXB",
    "owner": "user:US_39CUCTGTVBB",
    "createdAt": 1648364651822,
    "name": "Plaid Checking 0000",
    "defaultCurrency": "USD",
    "fingerprint": "EH6HMC/UfK+45MdA9s+RlVE3mzbROARQiT5KGh26c94=",
    "status": "PENDING",
    "statusMessage": null,
    "waitingPrompts": [],
    "linkType": "LOCAL_TRANSFER",
    "beneficiaryType": "UNKNOWN",
    "supportsDeposit": true,
    "nameOnMethod": null,
    "last4Digits": "0000",
    "brand": null,
    "expirationDisplay": null,
    "countryCode": "US",
    "nickname": null,
    "rejectionMessage": null,
    "disabled": false,
    "supportsPayment": true,
    "chargeableCurrencies": [
        "USD"
    ],
    "depositableCurrencies": [
        "USD"
    ],
    "chargeFeeSchedule": null,
    "depositFeeSchedule": null,
    "minCharge": null,
    "maxCharge": null,
    "minDeposit": null,
    "maxDeposit": null,
    "documents": [],
    "blockchains": {},
    "liquidationBalances": {},
    "srn": "paymentmethod:PA_DZ9WJXQEPXB"
}

Alternative to Plaid, you can connect a bank account by passing in bank and beneficiary information

## leave paymentMethodType as INTERNATIONAL_TRANSFER regardless of users location
curl --location --request POST 'https://api.testwyre.com/v2/paymentMethods?masqueradeAs=user:US_39CUCTGTVBB' \
--header 'Authorization: Bearer SK-86Z8FYFB-UTA2RDCN-HCZBFT2V-xxx' \
--header 'Content-Type: application/json' \
--data-raw '{
     "paymentMethodType": "INTERNATIONAL_TRANSFER", 
     "paymentType": "LOCAL_BANK_WIRE",
     "currency": "USD",
     "country": "US",
     "beneficiaryType": "INDIVIDUAL",
     "firstNameOnAccount": "Alberta",
     "lastNameOnAccount": "Charleson",
     "beneficiaryAddress": "2992 Cameron Road",
     "beneficiaryAddress2": "",
     "beneficiaryCity": "Malakoff",
     "beneficiaryPostal": "14236",
     "beneficiaryPhoneNumber": "+15555555555",
     "beneficaryState": "NY",
     "beneficiaryDobDay": 2,
     "beneficiaryDobMonth": 12,
     "beneficiaryDobYear": 1990,
     "accountNumber": "1234567890123",
     "routingNumber": "123412312",
     "accountType": "CHECKING",
     "chargeablePM": true
}'

#response:
{
    "id": "PA_PTXN82CCWRH",
    "owner": "user:US_39CUCTGTVBB",
    "createdAt": 1648783498152,
    "name": "USD Bank account ending in 0123",
    "defaultCurrency": "USD",
    "fingerprint": "BANK-bZwB7bB30jWoskzil4q13Vd9oxqn4g3mLhdUGd+dDIA=",
    "status": "ACTIVE",
    "statusMessage": null,
    "waitingPrompts": [],
    "linkType": "INTERNATIONAL_TRANSFER",
    "beneficiaryType": "INDIVIDUAL",
    "supportsDeposit": true,
    "nameOnMethod": "Alberta Charleson",
    "last4Digits": "0123",
    "brand": null,
    "expirationDisplay": null,
    "countryCode": "US",
    "nickname": null,
    "rejectionMessage": null,
    "disabled": false,
    "supportsPayment": true,
    "chargeableCurrencies": [
        "USD"
    ],
    "depositableCurrencies": [
        "USD"
    ],
    "chargeFeeSchedule": null,
    "depositFeeSchedule": null,
    "minCharge": null,
    "maxCharge": null,
    "minDeposit": null,
    "maxDeposit": null,
    "documents": [],
    "blockchains": {},
    "liquidationBalances": {},
    "srn": "paymentmethod:PA_PTXN82CCWRH"
}

Step 4: Fund your Wyre User

You can pull funds into Wyre using a payment method as the source.

curl --location --request POST 'https://api.testwyre.com/v3/transfers' \
--header 'Authorization: Bearer SK-86Z8FYFB-UTA2RDCN-HCZBFT2V-xxx' \
--header 'Content-Type: application/json' \
--data-raw '{
     "source": "paymentmethod:PA_DZ9WJXQEPXB",
     "sourceCurrency": "USD",
     "sourceAmount": "200",
     "dest": "user:user:US_39CUCTGTVBB",
     "destCurrency": "USD",
     "message": "Sending USD to the payment method",
     "autoConfirm": true
}'

#response
{
    "pusherChannel": "3ae4c645a03b0e3ca2087de85960975c",
    "exchangeRate": null,
    "destAmount": 200.00,
    "createdAt": 1648365385000,
    "destCurrency": "USD",
    "sourceAmount": 201.00,
    "sourceCurrency": "USD",
    "dest": "user:user:US_39CUCTGTVBB",
    "fees": {
        "USD": 1.00
    },
    "totalFees": 1.00,
    "customId": null,
    "completedAt": null,
    "cancelledAt": null,
    "failureReason": null,
    "blockchainTx": null,
    "expiresAt": 1648366285000,
    "updatedAt": null,
    "estimatedArrival": 1649056585076,
    "reversingSubStatus": null,
    "reversalReason": null,
    "pendingSubStatus": "IN_REVIEW",
    "statusHistories": [],
    "message": "Sending USD to the payment method",
    "id": "TF_JDYQ6GJ8972",
    "owner": "account:AC_YC3NT6GEZ8U",
    "source": "paymentmethod:PA_DZ9WJXQEPXB",
    "status": "PENDING"
}

Step 5: Use Wyre's Transfers API

Through Wyre's Transfers API you can do several things including exchange funds from fiat into crypto, send funds in the form of fiat or crypto to another user, and cashing out to your bank account

# a simple fiat to fiat transfer similar to a cash app/venmo payment

curl --location --request POST 'https://api.testwyre.com/v3/transfers' \
--header 'Authorization: Bearer SK-86Z8FYFB-UTA2RDCN-HCZBFT2V-xxx' \
--header 'Content-Type: application/json' \
--data-raw '{
     "source": "user:US_39CUCTGTVBB",
     "sourceCurrency": "USD",
     "sourceAmount": "20",
     "dest": "user:US_CTJFZPA7Q9Q",
     "destCurrency": "USD",
     "message": "Sending USD to US_CTJFZPA7Q9Q",
     "autoConfirm": true
}'
# doing a currency exchange for a user

curl --location --request POST 'https://api.testwyre.com/v3/transfers' \
--header 'Authorization: Bearer SK-86Z8FYFB-UTA2RDCN-HCZBFT2V-xxx' \
--header 'Content-Type: application/json' \
--data-raw '{
     "source": "user:US_39CUCTGTVBB",
     "sourceCurrency": "USD",
     "sourceAmount": "20",
     "dest": "user:US_39CUCTGTVBB",
     "destCurrency": "BTC",
     "message": "converting USD to BTC for user:US_39CUCTGTVBB",
     "autoConfirm": true
}'
# paying out to bank account

curl --location --request POST 'https://api.testwyre.com/v3/transfers' \
--header 'Authorization: Bearer SK-86Z8FYFB-UTA2RDCN-HCZBFT2V-xxx' \
--header 'Content-Type: application/json' \
--data-raw '{
     "source": "user:US_39CUCTGTVBB",
     "sourceCurrency": "USD",
     "sourceAmount": "20",
     "dest": "paymentmethod:PA_DZ9WJXQEPXB",
     "destCurrency": "USD",
     "message": "sending USD to bank account",
     "autoConfirm": true
}'