You have two options to send USDC and other tokens.
Remember that you need to update the .env.local file for each new variable you have retrieved.
After you have a sender and a receiver wallet, it is time for your first transaction.
Javascript Code to Send 1 USDC Token
import dotenv from "dotenv";
import fetch from "node-fetch";
import { acquire_session_token } from "../helpers/acquire_session_token.js";
import { v4 as uuidv4 } from "uuid";
dotenv.config();
const userCredentials = await acquire_session_token();
const userToken = userCredentials.userToken;
const encryptionKey = userCredentials.encryptionKey;
const idempotencyKey = uuidv4();
const url = "<<https://api.circle.com/v1/w3s/user/transactions/transfer>>";
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.API_KEY}`,
"X-User-Token": userToken,
},
body: JSON.stringify({
idempotencyKey: idempotencyKey,
userId: `${process.env.USER_ID}`,
destinationAddress: `${process.env.ADDRESS_R}`,
refId: "",
amounts: \\\["1"\\\],
feeLevel: "HIGH",
tokenId: `${process.env.USDC_TOKEN_ID}`,
walletId: `${process.env.WALLET_ID}`,
}),
};
fetch(url, options)
.then((res) => res.json())
.then((json) => {
console.log("user token:", userToken);
console.log("encryption key:", encryptionKey);
console.log("idempotency key:", idempotencyKey);
console.log(json);
})
.catch((err) => console.error("error:" + err));
Now, let's break down this code to understand it better.
import dotenv from "dotenv";
import fetch from "node-fetch";
import { acquire_session_token } from "../helpers/acquire_session_token.js";
import { v4 as uuidv4 } from "uuid";
Here you import the necessary libraries and codes.
dotenv and fetch have the same purpose as in the previous examples to use the .env file and to be able to make fetch calls to the api.acquire_session_token this is the same function as you used in the user-controlled wallet project. Now, this code returns an object that has a userToken and encryption key.uuid: to create the idempotency key with a unique identifier.const url = "<<https://api.circle.com/v1/w3s/user/transactions/transfer>>";
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.API_KEY}`,
"X-User-Token": userToken,
},
body: JSON.stringify({
idempotencyKey: idempotencyKey,
userId: `${process.env.USER_ID}`,
destinationAddress: `${process.env.ADDRESS_R}`,
refId: "",
amounts: \\\["1"\\\],
feeLevel: "HIGH",
tokenId: `${process.env.USDC_TOKEN_ID}`,
walletId: `${process.env.WALLET_ID}`,
}),
};
url is where you send the POST request.body: this contains the information for your transaction.idempotency key: This uniquely identifies the transaction.userId: This is the id of the user who makes the transaction.destinationAddress: This is the address of the wallet that receives the funds.amounts: Amount of token to be transferred.feeLevel: This indicates the amount of fee to be used for the transaction.tokenId: The id of the token to be sent (in this case the id of the USDC token that you have retrieved in the previous lesson).walletId: Id of the wallet that sends the fundsfetch(url, options)
.then((res) => res.json())
.then((json) => {
console.log("user token:", userToken);
console.log("encryption key:", encryptionKey);
console.log("idempotency key:", idempotencyKey);
console.log(json);
})
.catch((err) => console.error("error:" + err));
This code returns a challengeId inside a json object. You are going to use this challenge id as you used before when you played the part of the end user and created a wallet by setting up a pin code and a recovery question. Since this is a user controlled wallet, you need the authorization from the end user. This is true for wallet creation and this is also true for transaction. For that, reason, please save this challenge id for the next part.
Completing the Challenge
Now that you have the user token (session token), encryption key, and Challenge Id, you can again play the role of the end user and complete the challenge for your transaction to be successful.
user-controlled-wallet project, where you have created the user controlled wallet.You have used that page before to create a wallet. This time, you are going to use this for completing a transaction. The reason you can use the same structure is because of the challenge. In the user controlled wallet, after you have done your part, you will require the authorization of the user. In Circle, you do this with a challenge. That is why in both creating a user controlled wallet, and creating a transaction, at the end, you have acquired a challenge id. You will use the same parameters as before: APP ID. USER ID, USER(SESSION) TOKEN, ENCRYPTION KEY and CHALLENGE ID. You have acquired these values if you followed the previous steps.
Summary
Creating a transaction has two main parts:
Developer acquires the session token, encryption key and challenge id. Putting the necessary parameters makes the api call.
User completes this transaction by completing the challenge by putting the pin code.
Swap insights and ask questions about “Learn everything about Circle and USDC”.
Ask a question or share your thoughts about this lesson.