Using the Hedgey APIs for Token Claims
Use these instructions to build your own claim button.
The simplest way to get started is to use the Hedgey Claims app to setup your token claim. Then you can use our API endpoint to pull the merkle tree proof and data to display the amount of tokens claimable, and format the proof and information required to create and send the on-chain transaction for your users to make their claim of tokens or vesting stream.
Once you have setup your claim, we will auto-generate a claim page for you. The claim page URL contains the unique UUID required by the API and the smart contract for making claims. This unique ID can be found in the URL or in the space for copying the claim page URL.
For example the id value will look something like fe48cfdd-5809-4bc1-a47f-1c526b36cf5f
The token claim product uses a merkle tree to compress the information to claim, as a result the wallet claiming needs a proof value. This proof value can be obtained by using an API.
The endpoint URL is
https://api.hedgey.finance/token-claims/proof/{uuid}/{address}
A GET request should be made to this endpoint with replacing {uuid} and {address} with real values. The uuid value is the id of the claim and the address is the address of the wallet that is making the claim.
Below is a response example, if the wallet can carry out a claim.
{
"canClaim": true,
"proof": [
"0x1f14d0d899eb52d9467e3d3888cc2741d4d915ff13e29a1aac99dfcfea6a0d0f",
"0x54ada740ae82a2249e2ce9827394e765937e62a128f25045605c255ea7d42f24",
"0xbf3ee7814439a23ac477953252877c633372fe8c7fde8c0d2ece57a4eca3904f",
"0x5db1bea240bf7d6de115167e18e2d88e070e79e859a326b6bf7b4e21947a8302"
],
"amount": "1000000000000000000"
}
Below is a response example, if the wallet cannot carry out a claim.
{
"canClaim": false,
"amount": "0"
}
Check if an address has already claimed on chain
To convert the UUID to the hex value:
const generatedUUID = "c7102bd7-3357-4abf-9991-4d80bba77f19";
const hexId =
0x${generatedUUID.replace(/-/g, "")}
const isClaimed = async (
publicClient: PublicClient,
contractAddress: string,
uuid: string,
claimant: string
): Promise<boolean> => {
const hexId = bytesToHex(convertUUIDToUint8Array(uuid));
const claimed = await publicClient.readContract({
abi: delegatedClaimCampaign,
address: contractAddress,
functionName: "claimed",
args: [hexId, claimant],
});
return claimed as boolean;
};
A stripped down version of the ABI required to make the call
[
{
inputs: [
{
internalType: 'bytes16',
name: '',
type: 'bytes16',
},
{
internalType: 'address',
name: '',
type: 'address',
},
],
name: 'claimed',
outputs: [
{
internalType: 'bool',
name: '',
type: 'bool',
},
],
stateMutability: 'view',
type: 'function',
}
]
Once the user has the proof value from the above call they can then make a web3 call using the wallet that is eligible to claim.
A stripped down version of the ABI required to make the call
[
{
"inputs": [
{
"internalType": "bytes16",
"name": "campaignId",
"type": "bytes16"
},
{
"internalType": "bytes32[]",
"name": "proof",
"type": "bytes32[]"
},
{
"internalType": "uint256",
"name": "claimAmount",
"type": "uint256"
}
],
"name": "claim",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
campaignId: The uuid converted to a hex array. proof: The proof string array retrieved from the endpoint. claimAmount: The claim amount retrieved from the endpoint.
Converting the uuid to a hex array using viem and uuid
Step one, parse the uuid string into a byte array using parse Step two, parse the byte array into a hex value.
import { parse } from 'uuid';
import { bytesToHex } from 'viem';
const bytesArray = parse('fe48cfdd-5809-4bc1-a47f-1c526b36cf5f');
const hexId = bytesToHex(bytesArray);
The hexId value can then be used in the contract call. An example of calling this web3 method using viem:
const hash = await walletClient.writeContract({
abi: delegatedClaimCampaign,
address: contractAddress,
functionName: 'claim',
args: [hexId, proof, BigInt(amount)],
account: claimant,
chain,
});
For AirVest and AirStream the wallet will receive a plan they can use to redeem locked tokens according to the configured schedule.
For AirClaim there is an option for the tokens to be transferred directly to the claimant.
Full ABI for the Delegate Token Claim contract
[
{
inputs: [
{
internalType: 'string',
name: 'name',
type: 'string',
},
{
internalType: 'string',
name: 'version',
type: 'string',
},
{
internalType: 'address[]',
name: '_tokenLockups',
type: 'address[]',
},
],
stateMutability: 'nonpayable',
type: 'constructor',
},
{
inputs: [
{
internalType: 'address',
name: 'target',
type: 'address',
},
],
name: 'AddressEmptyCode',
type: 'error',
},
{
inputs: [
{
internalType: 'address',
name: 'account',
type: 'address',
},
],
name: 'AddressInsufficientBalance',
type: 'error',
},
{
inputs: [],
name: 'ECDSAInvalidSignature',
type: 'error',
},
{
inputs: [
{
internalType: 'uint256',
name: 'length',
type: 'uint256',
},
],
name: 'ECDSAInvalidSignatureLength',
type: 'error',
},
{
inputs: [
{
internalType: 'bytes32',
name: 's',
type: 'bytes32',
},
],
name: 'ECDSAInvalidSignatureS',
type: 'error',
},
{
inputs: [],
name: 'FailedInnerCall',
type: 'error',
},
{
inputs: [
{
internalType: 'address',
name: 'account',
type: 'address',
},
{
internalType: 'uint256',
name: 'currentNonce',
type: 'uint256',
},
],
name: 'InvalidAccountNonce',
type: 'error',
},
{
inputs: [],
name: 'InvalidShortString',
type: 'error',
},
{
inputs: [],
name: 'ReentrancyGuardReentrantCall',
type: 'error',
},
{
inputs: [
{
internalType: 'address',
name: 'token',
type: 'address',
},
],
name: 'SafeERC20FailedOperation',
type: 'error',
},
{
inputs: [
{
internalType: 'string',
name: 'str',
type: 'string',
},
],
name: 'StringTooLong',
type: 'error',
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: 'bytes16',
name: 'id',
type: 'bytes16',
},
],
name: 'CampaignCancelled',
type: 'event',
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: 'bytes16',
name: 'id',
type: 'bytes16',
},
{
components: [
{
internalType: 'address',
name: 'manager',
type: 'address',
},
{
internalType: 'address',
name: 'token',
type: 'address',
},
{
internalType: 'uint256',
name: 'amount',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'start',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'end',
type: 'uint256',
},
{
internalType: 'enum DelegatedClaimCampaigns.TokenLockup',
name: 'tokenLockup',
type: 'uint8',
},
{
internalType: 'bytes32',
name: 'root',
type: 'bytes32',
},
{
internalType: 'bool',
name: 'delegating',
type: 'bool',
},
],
indexed: false,
internalType: 'struct DelegatedClaimCampaigns.Campaign',
name: 'campaign',
type: 'tuple',
},
{
indexed: false,
internalType: 'uint256',
name: 'totalClaimers',
type: 'uint256',
},
],
name: 'CampaignStarted',
type: 'event',
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: 'bytes16',
name: 'id',
type: 'bytes16',
},
{
components: [
{
internalType: 'address',
name: 'tokenLocker',
type: 'address',
},
{
internalType: 'uint256',
name: 'start',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'cliff',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'period',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'periods',
type: 'uint256',
},
],
indexed: false,
internalType: 'struct DelegatedClaimCampaigns.ClaimLockup',
name: 'claimLockup',
type: 'tuple',
},
],
name: 'ClaimLockupCreated',
type: 'event',
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: 'address',
name: 'recipient',
type: 'address',
},
{
indexed: true,
internalType: 'uint256',
name: 'amount',
type: 'uint256',
},
],
name: 'Claimed',
type: 'event',
},
{
anonymous: false,
inputs: [],
name: 'EIP712DomainChanged',
type: 'event',
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: 'bytes16',
name: 'id',
type: 'bytes16',
},
{
indexed: true,
internalType: 'address',
name: 'claimer',
type: 'address',
},
{
indexed: true,
internalType: 'uint256',
name: 'tokenId',
type: 'uint256',
},
{
indexed: false,
internalType: 'uint256',
name: 'amountClaimed',
type: 'uint256',
},
{
indexed: false,
internalType: 'uint256',
name: 'amountRemaining',
type: 'uint256',
},
],
name: 'LockedTokensClaimed',
type: 'event',
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: 'bytes16',
name: 'id',
type: 'bytes16',
},
{
indexed: true,
internalType: 'address',
name: 'claimer',
type: 'address',
},
{
indexed: false,
internalType: 'uint256',
name: 'amountClaimed',
type: 'uint256',
},
{
indexed: false,
internalType: 'uint256',
name: 'amountRemaining',
type: 'uint256',
},
],
name: 'UnlockedTokensClaimed',
type: 'event',
},
{
inputs: [
{
internalType: 'bytes16',
name: '',
type: 'bytes16',
},
],
name: 'campaigns',
outputs: [
{
internalType: 'address',
name: 'manager',
type: 'address',
},
{
internalType: 'address',
name: 'token',
type: 'address',
},
{
internalType: 'uint256',
name: 'amount',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'start',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'end',
type: 'uint256',
},
{
internalType: 'enum DelegatedClaimCampaigns.TokenLockup',
name: 'tokenLockup',
type: 'uint8',
},
{
internalType: 'bytes32',
name: 'root',
type: 'bytes32',
},
{
internalType: 'bool',
name: 'delegating',
type: 'bool',
},
],
stateMutability: 'view',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes16[]',
name: 'campaignIds',
type: 'bytes16[]',
},
],
name: 'cancelCampaigns',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes16',
name: 'campaignId',
type: 'bytes16',
},
{
internalType: 'bytes32[]',
name: 'proof',
type: 'bytes32[]',
},
{
internalType: 'uint256',
name: 'claimAmount',
type: 'uint256',
},
],
name: 'claim',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes16',
name: 'campaignId',
type: 'bytes16',
},
{
internalType: 'bytes32[]',
name: 'proof',
type: 'bytes32[]',
},
{
internalType: 'uint256',
name: 'claimAmount',
type: 'uint256',
},
{
internalType: 'address',
name: 'delegatee',
type: 'address',
},
{
components: [
{
internalType: 'uint256',
name: 'nonce',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'expiry',
type: 'uint256',
},
{
internalType: 'uint8',
name: 'v',
type: 'uint8',
},
{
internalType: 'bytes32',
name: 'r',
type: 'bytes32',
},
{
internalType: 'bytes32',
name: 's',
type: 'bytes32',
},
],
internalType: 'struct DelegatedClaimCampaigns.SignatureParams',
name: 'delegationSignature',
type: 'tuple',
},
],
name: 'claimAndDelegate',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes16',
name: 'campaignId',
type: 'bytes16',
},
{
internalType: 'bytes32[]',
name: 'proof',
type: 'bytes32[]',
},
{
internalType: 'address',
name: 'claimer',
type: 'address',
},
{
internalType: 'uint256',
name: 'claimAmount',
type: 'uint256',
},
{
components: [
{
internalType: 'uint256',
name: 'nonce',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'expiry',
type: 'uint256',
},
{
internalType: 'uint8',
name: 'v',
type: 'uint8',
},
{
internalType: 'bytes32',
name: 'r',
type: 'bytes32',
},
{
internalType: 'bytes32',
name: 's',
type: 'bytes32',
},
],
internalType: 'struct DelegatedClaimCampaigns.SignatureParams',
name: 'claimSignature',
type: 'tuple',
},
{
internalType: 'address',
name: 'delegatee',
type: 'address',
},
{
components: [
{
internalType: 'uint256',
name: 'nonce',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'expiry',
type: 'uint256',
},
{
internalType: 'uint8',
name: 'v',
type: 'uint8',
},
{
internalType: 'bytes32',
name: 'r',
type: 'bytes32',
},
{
internalType: 'bytes32',
name: 's',
type: 'bytes32',
},
],
internalType: 'struct DelegatedClaimCampaigns.SignatureParams',
name: 'delegationSignature',
type: 'tuple',
},
],
name: 'claimAndDelegateWithSig',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes16',
name: '',
type: 'bytes16',
},
],
name: 'claimLockups',
outputs: [
{
internalType: 'address',
name: 'tokenLocker',
type: 'address',
},
{
internalType: 'uint256',
name: 'start',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'cliff',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'period',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'periods',
type: 'uint256',
},
],
stateMutability: 'view',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes16[]',
name: 'campaignIds',
type: 'bytes16[]',
},
{
internalType: 'bytes32[][]',
name: 'proofs',
type: 'bytes32[][]',
},
{
internalType: 'uint256[]',
name: 'claimAmounts',
type: 'uint256[]',
},
],
name: 'claimMultiple',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes16[]',
name: 'campaignIds',
type: 'bytes16[]',
},
{
internalType: 'bytes32[][]',
name: 'proofs',
type: 'bytes32[][]',
},
{
internalType: 'address',
name: 'claimer',
type: 'address',
},
{
internalType: 'uint256[]',
name: 'claimAmounts',
type: 'uint256[]',
},
{
components: [
{
internalType: 'uint256',
name: 'nonce',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'expiry',
type: 'uint256',
},
{
internalType: 'uint8',
name: 'v',
type: 'uint8',
},
{
internalType: 'bytes32',
name: 'r',
type: 'bytes32',
},
{
internalType: 'bytes32',
name: 's',
type: 'bytes32',
},
],
internalType: 'struct DelegatedClaimCampaigns.SignatureParams',
name: 'claimSignature',
type: 'tuple',
},
],
name: 'claimMultipleWithSig',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes16',
name: 'campaignId',
type: 'bytes16',
},
{
internalType: 'bytes32[]',
name: 'proof',
type: 'bytes32[]',
},
{
internalType: 'address',
name: 'claimer',
type: 'address',
},
{
internalType: 'uint256',
name: 'claimAmount',
type: 'uint256',
},
{
components: [
{
internalType: 'uint256',
name: 'nonce',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'expiry',
type: 'uint256',
},
{
internalType: 'uint8',
name: 'v',
type: 'uint8',
},
{
internalType: 'bytes32',
name: 'r',
type: 'bytes32',
},
{
internalType: 'bytes32',
name: 's',
type: 'bytes32',
},
],
internalType: 'struct DelegatedClaimCampaigns.SignatureParams',
name: 'claimSignature',
type: 'tuple',
},
],
name: 'claimWithSig',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes16',
name: '',
type: 'bytes16',
},
{
internalType: 'address',
name: '',
type: 'address',
},
],
name: 'claimed',
outputs: [
{
internalType: 'bool',
name: '',
type: 'bool',
},
],
stateMutability: 'view',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes16',
name: 'id',
type: 'bytes16',
},
{
components: [
{
internalType: 'address',
name: 'manager',
type: 'address',
},
{
internalType: 'address',
name: 'token',
type: 'address',
},
{
internalType: 'uint256',
name: 'amount',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'start',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'end',
type: 'uint256',
},
{
internalType: 'enum DelegatedClaimCampaigns.TokenLockup',
name: 'tokenLockup',
type: 'uint8',
},
{
internalType: 'bytes32',
name: 'root',
type: 'bytes32',
},
{
internalType: 'bool',
name: 'delegating',
type: 'bool',
},
],
internalType: 'struct DelegatedClaimCampaigns.Campaign',
name: 'campaign',
type: 'tuple',
},
{
components: [
{
internalType: 'address',
name: 'tokenLocker',
type: 'address',
},
{
internalType: 'uint256',
name: 'start',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'cliff',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'period',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'periods',
type: 'uint256',
},
],
internalType: 'struct DelegatedClaimCampaigns.ClaimLockup',
name: 'claimLockup',
type: 'tuple',
},
{
internalType: 'address',
name: 'vestingAdmin',
type: 'address',
},
{
internalType: 'uint256',
name: 'totalClaimers',
type: 'uint256',
},
],
name: 'createLockedCampaign',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes16',
name: 'id',
type: 'bytes16',
},
{
components: [
{
internalType: 'address',
name: 'manager',
type: 'address',
},
{
internalType: 'address',
name: 'token',
type: 'address',
},
{
internalType: 'uint256',
name: 'amount',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'start',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'end',
type: 'uint256',
},
{
internalType: 'enum DelegatedClaimCampaigns.TokenLockup',
name: 'tokenLockup',
type: 'uint8',
},
{
internalType: 'bytes32',
name: 'root',
type: 'bytes32',
},
{
internalType: 'bool',
name: 'delegating',
type: 'bool',
},
],
internalType: 'struct DelegatedClaimCampaigns.Campaign',
name: 'campaign',
type: 'tuple',
},
{
internalType: 'uint256',
name: 'totalClaimers',
type: 'uint256',
},
],
name: 'createUnlockedCampaign',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [],
name: 'eip712Domain',
outputs: [
{
internalType: 'bytes1',
name: 'fields',
type: 'bytes1',
},
{
internalType: 'string',
name: 'name',
type: 'string',
},
{
internalType: 'string',
name: 'version',
type: 'string',
},
{
internalType: 'uint256',
name: 'chainId',
type: 'uint256',
},
{
internalType: 'address',
name: 'verifyingContract',
type: 'address',
},
{
internalType: 'bytes32',
name: 'salt',
type: 'bytes32',
},
{
internalType: 'uint256[]',
name: 'extensions',
type: 'uint256[]',
},
],
stateMutability: 'view',
type: 'function',
},
{
inputs: [
{
internalType: 'address',
name: 'owner',
type: 'address',
},
],
name: 'nonces',
outputs: [
{
internalType: 'uint256',
name: '',
type: 'uint256',
},
],
stateMutability: 'view',
type: 'function',
},
{
inputs: [
{
internalType: 'address',
name: '',
type: 'address',
},
{
internalType: 'address',
name: '',
type: 'address',
},
{
internalType: 'uint256',
name: '',
type: 'uint256',
},
{
internalType: 'bytes',
name: '',
type: 'bytes',
},
],
name: 'onERC721Received',
outputs: [
{
internalType: 'bytes4',
name: '',
type: 'bytes4',
},
],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [
{
internalType: 'address',
name: '',
type: 'address',
},
],
name: 'tokenLockers',
outputs: [
{
internalType: 'bool',
name: '',
type: 'bool',
},
],
stateMutability: 'view',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes16',
name: '',
type: 'bytes16',
},
],
name: 'usedIds',
outputs: [
{
internalType: 'bool',
name: '',
type: 'bool',
},
],
stateMutability: 'view',
type: 'function',
},
{
inputs: [
{
internalType: 'bytes32',
name: 'root',
type: 'bytes32',
},
{
internalType: 'bytes32[]',
name: 'proof',
type: 'bytes32[]',
},
{
internalType: 'address',
name: 'claimer',
type: 'address',
},
{
internalType: 'uint256',
name: 'amount',
type: 'uint256',
},
],
name: 'verify',
outputs: [
{
internalType: 'bool',
name: '',
type: 'bool',
},
],
stateMutability: 'pure',
type: 'function',
},
]
Last updated