Transaction Lifecycle
How OPENFORMAT creates and broadcasts transactions
In the OPENFORMAT transaction lifecycle, the app owner takes on the responsibility of paying for the gas fees when rewarding tokens and badges. This is improves the UX for the user and also allows app owners to estimate costs for running their applications.
Create Reward Transaction
The process begins with the creation of a reward transaction. This involves calling a Reward transaction endpoint, which returns an unsigned Ethereum transaction containing all the necessary details to reward a user.
curl --request POST \
--url https://api.openformat.tech/v1/reward/XP \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <x-api-key>' \
--data '{
"app_id": "0x456",
"action_id": "share_tweet",
"receiver": "0x123",
"amount": 123
}'
Verify and Sign the Transaction
After receiving the unsigned transaction, it’s your responsibility to verify and sign it with your private key. This crucial step ensures security since we don’t access your private keys. You have the option to sign the transaction on the frontend using Viem or ethers. based on your preference.
import { ethers } from "ethers";
const privateKey = "your-private-key";
const wallet = new ethers.Wallet(privateKey);
async function sign() {
const unsignedTransactionFromAPI = {
to: "0x014b680bed2433b1861239cf812dbe660fe339f2",
data: "0x609512c90000000000000000000000009574e9ba92cb0966c9d2ff1a9ab9e11949b9b87300000000000000000000000003755...",
maxPriorityFeePerGas: "30000000000",
maxFeePerGas: "30000000015",
gasLimit: "77667",
nonce: 2476,
chainId: 80001,
type: 2,
};
const signed = await wallet.signTransaction(
unsignedTransactionFromAPI
);
console.log(signed);
//0x02f90157830138818209ac8506fc23ac008506fc23ac0f83012f63......
}
sign();
Execute the Transaction
Finally, once you’ve signed the transaction, it’s ready to be sent to the network. We offer to handle this step for you, leveraging our advanced execution process that includes efficient nonce management and queue integration. This ensures a smooth and reliable transaction execution. However, you also have the option to process the transaction yourself or use any existing service you’re accustomed to.
curl --request POST \
--url https://api.openformat.tech/v1/transactions/execute \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <x-api-key>' \
--data '{
"signed_transaction": "0x123"
}'
We also provide another endpoint in case you need to wait for the result of the transaction execution.
curl --request POST \
--url https://api.openformat.tech/v1/transactions/execute-and-wait \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <x-api-key>' \
--data '{
"signed_transaction": "0x123"
}'
Examples
import axios from "axios";
import { ethers } from "ethers";
// Setup environment variables.
const privateKey = process.env["PRIVATE_KEY"];
const apiURL = process.env["API_ENDPOINT"];
const apiKey = process.env["API_KEY"];
// Setup wallet for signing transaction.
const wallet = new ethers.Wallet(privateKey!);
// Setup axios instance.
const apiClient = axios.create({
baseURL: apiURL,
headers: {
"X-API-KEY": apiKey,
"Content-Type": "application/json",
"accept-encoding": "gzip",
},
});
// Create and Broadcast Reward XP Transaction to Polygon Mumbai network.
async function rewardXP() {
try {
const data = {
app_id: "[YOUR_APP_ID]",
action_id: "complete_activity",
receiver: "[RECEIVER_WALLET_ADDRESS]",
amount: 5,
};
const res = await apiClient.post("/reward/XP", data);
const signedTransaction = await wallet.signTransaction(
res.data.unsignedTransaction
);
const broadcast = await apiClient.post("/transactions/execute", {
signed_transaction: signedTransaction,
});
console.log(broadcast.data);
} catch (e) {
console.log("Err", e.message);
}
}
rewardXP();
// {
// status: "SUCCESS",
// transactionHash: "0x4c25f51e5c33ccbcee491f222ef6707ff5ee5b76c2ec2f252126c6130dccd3a4",
// blockExplorerUrl: "https://mumbai.polygonscan.com/tx/0x4c25f51e5c33ccbcee491f222ef6707ff5ee5b76c2ec2f252126c6130dccd3a4",
// }