Processing redeem requests
The typical flow to process redeem requests from your user
To do a redeem, you must first perform a burn transaction on the blockchain, then use the hash of that transaction as a parameter in the POST /api/transaction/redeem-request
endpoint. Here is an example code to perform a burn transaction. In this example, we will be using Alchemy as the RPC provider, and Polygon as the blockchain. Please note that for the bank account hash, the format is {bankName}_{bankAccountNumber}
.
import sha256 from 'crypto-js/sha256';
const { ethers } = require("ethers");
const idrxAbi = [{"inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "address", "name": "_user", "type": "address" } ], "name": "AddedBlackList", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "address", "name": "previousAdmin", "type": "address" }, {"indexed": false, "internalType": "address", "name": "newAdmin", "type": "address" } ], "name": "AdminChanged", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": true, "internalType": "address", "name": "owner", "type": "address" }, {"indexed": true, "internalType": "address", "name": "spender", "type": "address" }, {"indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Approval", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": true, "internalType": "address", "name": "beacon", "type": "address" } ], "name": "BeaconUpgraded", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "address", "name": "_user", "type": "address" }, {"indexed": false, "internalType": "uint256", "name": "_amount", "type": "uint256" }, {"indexed": false, "internalType": "uint256", "name": "amountAfterCut", "type": "uint256" }, {"indexed": false, "internalType": "uint256", "name": "toChain", "type": "uint256" }, {"indexed": false, "internalType": "uint256", "name": "_bridgeNonce", "type": "uint256" }, {"indexed": false, "internalType": "uint256", "name": "platformFee", "type": "uint256" } ], "name": "BurnBridge", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "address", "name": "_user", "type": "address" }, {"indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" }, {"indexed": false, "internalType": "string", "name": "hashedAccountNumber", "type": "string" } ], "name": "BurnWithAccountNumber", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "address", "name": "_blackListedUser", "type": "address" }, {"indexed": false, "internalType": "uint256", "name": "_balance", "type": "uint256" } ], "name": "DestroyedBlackFunds", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "uint8", "name": "version", "type": "uint8" } ], "name": "Initialized", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "address", "name": "_user", "type": "address" }, {"indexed": false, "internalType": "uint256", "name": "_amount", "type": "uint256" }, {"indexed": false, "internalType": "uint256", "name": "amountAfterCut", "type": "uint256" }, {"indexed": false, "internalType": "uint256", "name": "fromChain", "type": "uint256" }, {"indexed": false, "internalType": "uint256", "name": "fromBridgeNonce", "type": "uint256" }, {"indexed": false, "internalType": "uint256", "name": "platformFee", "type": "uint256" } ], "name": "MintBridge", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "address", "name": "account", "type": "address" } ], "name": "Paused", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "address", "name": "_platformFeeRecipient", "type": "address" }, {"indexed": false, "internalType": "uint64", "name": "_burnBridgeFee", "type": "uint64" }, {"indexed": false, "internalType": "uint64", "name": "_mintBridgeFee", "type": "uint64" } ], "name": "PlatformFeeInfoUpdated", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "address", "name": "_user", "type": "address" } ], "name": "RemovedBlackList", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": true, "internalType": "bytes32", "name": "role", "type": "bytes32" }, {"indexed": true, "internalType": "bytes32", "name": "previousAdminRole", "type": "bytes32" }, {"indexed": true, "internalType": "bytes32", "name": "newAdminRole", "type": "bytes32" } ], "name": "RoleAdminChanged", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": true, "internalType": "bytes32", "name": "role", "type": "bytes32" }, {"indexed": true, "internalType": "address", "name": "account", "type": "address" }, {"indexed": true, "internalType": "address", "name": "sender", "type": "address" } ], "name": "RoleGranted", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": true, "internalType": "bytes32", "name": "role", "type": "bytes32" }, {"indexed": true, "internalType": "address", "name": "account", "type": "address" }, {"indexed": true, "internalType": "address", "name": "sender", "type": "address" } ], "name": "RoleRevoked", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": true, "internalType": "address", "name": "from", "type": "address" }, {"indexed": true, "internalType": "address", "name": "to", "type": "address" }, {"indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "address", "name": "account", "type": "address" } ], "name": "Unpaused", "type": "event" }, {"anonymous": false, "inputs": [{"indexed": true, "internalType": "address", "name": "implementation", "type": "address" } ], "name": "Upgraded", "type": "event" }, {"inputs": [], "name": "BLACKLIST_ROLE", "outputs": [{"internalType": "bytes32", "name": "", "type": "bytes32" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "DEFAULT_ADMIN_ROLE", "outputs": [{"internalType": "bytes32", "name": "", "type": "bytes32" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "MINTER_ROLE", "outputs": [{"internalType": "bytes32", "name": "", "type": "bytes32" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "PAUSER_ROLE", "outputs": [{"internalType": "bytes32", "name": "", "type": "bytes32" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "PLATFORM_FEE_SETTER_ROLE", "outputs": [{"internalType": "bytes32", "name": "", "type": "bytes32" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "UPGRADER_ROLE", "outputs": [{"internalType": "bytes32", "name": "", "type": "bytes32" } ], "stateMutability": "view", "type": "function" }, {"inputs": [{"internalType": "address", "name": "", "type": "address" } ], "name": "_balances", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "_bridgeNonce", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "_totalSupply", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, {"inputs": [{"internalType": "address", "name": "_evilUser", "type": "address" } ], "name": "addBlackList", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "address", "name": "owner", "type": "address" }, {"internalType": "address", "name": "spender", "type": "address" } ], "name": "allowance", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, {"inputs": [{"internalType": "address", "name": "spender", "type": "address" }, {"internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "approve", "outputs": [{"internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "address", "name": "account", "type": "address" } ], "name": "balanceOf", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, {"inputs": [{"internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "burn", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "uint256", "name": "amount", "type": "uint256" }, {"internalType": "uint256", "name": "toChain", "type": "uint256" } ], "name": "burnBridge", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "address", "name": "account", "type": "address" }, {"internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "burnFrom", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "uint256", "name": "amount", "type": "uint256" }, {"internalType": "string", "name": "accountNumber", "type": "string" } ], "name": "burnWithAccountNumber", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [], "name": "decimals", "outputs": [{"internalType": "uint8", "name": "", "type": "uint8" } ], "stateMutability": "view", "type": "function" }, {"inputs": [{"internalType": "address", "name": "spender", "type": "address" }, {"internalType": "uint256", "name": "subtractedValue", "type": "uint256" } ], "name": "decreaseAllowance", "outputs": [{"internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "address", "name": "_blackListedUser", "type": "address" } ], "name": "destroyBlackFunds", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "uint256", "name": "", "type": "uint256" }, {"internalType": "uint256", "name": "", "type": "uint256" } ], "name": "fromChainNonceUsed", "outputs": [{"internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, {"inputs": [{"internalType": "address", "name": "_maker", "type": "address" } ], "name": "getBlackListStatus", "outputs": [{"internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "getPlatformFeeInfo", "outputs": [{"internalType": "address", "name": "", "type": "address" }, {"internalType": "uint64", "name": "", "type": "uint64" }, {"internalType": "uint64", "name": "", "type": "uint64" } ], "stateMutability": "view", "type": "function" }, {"inputs": [{"internalType": "bytes32", "name": "role", "type": "bytes32" } ], "name": "getRoleAdmin", "outputs": [{"internalType": "bytes32", "name": "", "type": "bytes32" } ], "stateMutability": "view", "type": "function" }, {"inputs": [{"internalType": "bytes32", "name": "role", "type": "bytes32" }, {"internalType": "address", "name": "account", "type": "address" } ], "name": "grantRole", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "bytes32", "name": "role", "type": "bytes32" }, {"internalType": "address", "name": "account", "type": "address" } ], "name": "hasRole", "outputs": [{"internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, {"inputs": [{"internalType": "address", "name": "spender", "type": "address" }, {"internalType": "uint256", "name": "addedValue", "type": "uint256" } ], "name": "increaseAllowance", "outputs": [{"internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [], "name": "initialize", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "address", "name": "", "type": "address" } ], "name": "isBlackListed", "outputs": [{"internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "maxPlatformFee", "outputs": [{"internalType": "uint64", "name": "", "type": "uint64" } ], "stateMutability": "view", "type": "function" }, {"inputs": [{"internalType": "address", "name": "to", "type": "address" }, {"internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "mint", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "address", "name": "to", "type": "address" }, {"internalType": "uint256", "name": "amount", "type": "uint256" }, {"internalType": "uint256", "name": "fromChain", "type": "uint256" }, {"internalType": "uint256", "name": "fromChainBridgeNonce", "type": "uint256" } ], "name": "mintBridge", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [], "name": "name", "outputs": [{"internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "pause", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [], "name": "paused", "outputs": [{"internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "proxiableUUID", "outputs": [{"internalType": "bytes32", "name": "", "type": "bytes32" } ], "stateMutability": "view", "type": "function" }, {"inputs": [{"internalType": "address", "name": "_clearedUser", "type": "address" } ], "name": "removeBlackList", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "bytes32", "name": "role", "type": "bytes32" }, {"internalType": "address", "name": "account", "type": "address" } ], "name": "renounceRole", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "bytes32", "name": "role", "type": "bytes32" }, {"internalType": "address", "name": "account", "type": "address" } ], "name": "revokeRole", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "address", "name": "_platformFeeRecipient", "type": "address" }, {"internalType": "uint64", "name": "_burnBridgeFee", "type": "uint64" }, {"internalType": "uint64", "name": "_mintBridgeFee", "type": "uint64" } ], "name": "setPlatformFeeInfo", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "bytes4", "name": "interfaceId", "type": "bytes4" } ], "name": "supportsInterface", "outputs": [{"internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "symbol", "outputs": [{"internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, {"inputs": [], "name": "totalSupply", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, {"inputs": [{"internalType": "address", "name": "to", "type": "address" }, {"internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transfer", "outputs": [{"internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "address", "name": "from", "type": "address" }, {"internalType": "address", "name": "to", "type": "address" }, {"internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transferFrom", "outputs": [{"internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [], "name": "unpause", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "address", "name": "newImplementation", "type": "address" } ], "name": "upgradeTo", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, {"inputs": [{"internalType": "address", "name": "newImplementation", "type": "address" }, {"internalType": "bytes", "name": "data", "type": "bytes" } ], "name": "upgradeToAndCall", "outputs": [], "stateMutability": "payable", "type": "function" } ];
const ALCHEMY_POLYGON_NETWORK = "matic";
const ALCHEMY_API_KEY = "{ALCHEMY API KEY}";
const WALLET_PRIVATE_KEY = "{WALLET PRIVATE KEY}";
const IDRX_CONTRACT_ADDRESS = "0x649a2DA7B28E0D54c13D5eFf95d3A660652742cC";
const provider = new ethers.providers.AlchemyProvider(ALCHEMY_POLYGON_NETWORK, ALCHEMY_API_KEY);
const signer = new ethers.Wallet(WALLET_PRIVATE_KEY, provider);
async function burnIdrx() {
const amount = "21000";
const bankAccountNumber = "BANK CENTRAL ASIA_7255759001"; // example bank account. format: {bankName}_{bankAccountNumber}
const hashBankAccountNumber = await sha256(bankAccountNumber).toString();
const idrxContract = new ethers.Contract(IDRX_CONTRACT_ADDRESS, idrxAbi, provider);
const idrxContractSigner = idrxContract.connect(signer);
const tx = await idrxContractSigner.burnWithAccountNumber(amount, hashBankAccountNumber);
const txHash = tx.hash;
console.log('txHash: ');
console.log(txHash);
}
burnIdrx();
After the burning transaction is confirmed on the blockchain, you can use the transaction hash obtained from that transaction to do a redeem request. To get the appropriate bankCode
and bankName
, you can refer to Transactions Methods API.
import { createSignature } from "./createSignature";
const axios = require('axios');
const apiKey = "{YOUR API KEY}";
const secret = "{YOUR SECRET}";
async function redeemRequest() {
const path = "https://idrx.co/api/transaction/redeem-request";
const req = {
"txHash": "0xa38c057222872d8e3d106ab5f9b86b7d1d6ade72d485eb01366650e45c8a65d1",
"networkChainId": "137",
"amountTransfer": "21000",
"bankAccount": "7255759001",
"bankCode": "014",
"bankName": "BANK CENTRAL ASIA",
"bankAccountName": "JOHN SMITH",
"walletAddress": "0x8BD53F7fF88fD895D3686fe6369a07432822d30F",
};
const bufferReq = Buffer.from(JSON.stringify(req), 'base64').toString('utf8');
const timestamp = Math.round((new Date()).getTime()).toString();
const sig = createSignature('POST', path, bufferReq, timestamp, secret);
const res = await axios.post(path, req, {
headers: {
'Content-Type': 'application/json',
'idrx-api-key': apiKey,
'idrx-api-sig': sig,
},
});
console.log('res.data: ');
console.log(res.data);
}
redeemRequest();
After a successful request, you will get a response as follows:
{
statusCode: 201,
message: 'success',
data: {
id: 100,
chainId: 137,
userId: 411,
requester: 'JOHN SMITH',
txHash: '0xa38c057222872d8e3d106ab5f9b86b7d1d6ade72d485eb01366650e45c8a65d1',
fromAddress: '0x8BD53F7fF88fD895D3686fe6369a07432822d30F',
amount: '16000',
bankName: 'BANK CENTRAL ASIA',
bankCode: '014',
bankAccountNumber: '7255759001',
bankAccountName: 'JOHN SMITH',
bankAccountNumberHash: null,
custRefNumber: '000028880723',
disburseId: 17610206,
burnStatus: 'REQUESTED',
createdAt: '2023-12-19T11:05:42.583Z',
updatedAt: '2023-12-19T11:05:42.583Z',
deleted: false,
reportStatus: 'NONE',
notes: null
}
}
To check the status of the transaction, you can use the Transaction History API.
The redeem request will be then processed shortly after. IDR will be transferred to the specified bank account number.
Last updated