Creating a Token Claim using the Hedgey APIs

Reference: https://github.com/hedgey-finance/DelegatedTokenClaims/blob/master/contracts/DelegatedClaimCampaigns.sol The Hedgey smart contract for token claims.

The token claim contract uses a merkle tree to efficiently manage many thousands of addresses and amounts that can claim.

This merkle tree can be created manually using something like the following library

https://github.com/OpenZeppelin/merkle-tree

Or the Hedgey API can be used, if the API is used a CSV file is uploaded and Hedgey will manage the process of creating the merkle tree and storing the proofs (which are needed for claiming).

Generate a UUID

Each claim is identified by a UUID. You can generate a UUID by calling the following endpoint:

https://api.hedgey.finance/token-claims/uuid

This will return a UUID in the following format:

{
  "uuid": "a6a05f79-ea04-4565-9852-285e0520fd1c",
  "hex": "0xa6a05f79ea0445659852285e0520fd1c"
}

The hex value is used to identify the claim in the smart contract.

Prepare the entry and generate a PUT URL

POST request to https://api.hedgey.finance/token-claims

{
  "uuid": "a6a05f79-ea04-4565-9852-285e0520fd1c", 
  "startDate": {start date}, 
  "endDate": {end date}, 
  "decimals": 18, 
  "title": "", 
  "html": "", 
  "headerImage": "", 
  "source": ""
}

This will return a pre signed URL that can be used to upload the CSV file.

The CSV file should contain a list with two columns: address and amount:

address,amount
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2,0.1
0xBE0eB53F46cd790Cd13851d5EFf43D12404d33E8,0.1
0x40B38765696e3d5d8d9d834D8AaD4bB6e418E489,0.1
0x47ac0Fb4F2D84898e4D9E7b4DaB3C24507a6D503,0.1
0xDf9Eb223bAFBE5c5271415C75aeCD68C21fE3D7F,0.1
0xDf9Eb223bAFBE5c5271415C75aeCD68C21fE3D7F,0.1
0xAa9c3a194C9E78085260dfC7EAcFef51653412Bf,1
0xC9067B440f60A94170b9490c88d2efDBA1a7c536,0.1
0x169691e59538e80fa2a01adf5b21ded376730335,0.1
0xC622Cd2D887031526E4802d37Cba6E77f057211e,0.1

Checks done on CSV:

  • Duplicate addresses are combined

  • Addresses are check summed, if there is an invalid address the entire CSV is rejected

  • Lowercase addresses are accepted

  • Amounts are in ETH, e.g. to send 1 wETH the value would be 1, to send 0.1 wETH the value would be 0.1

The CSV should be uploaded using PUT to the presigned URL returned in the previous step.

Claim info

GET request to https://api.hedgey.finance/token-claims/info/{uuid} will return the status of the claim

{
  "uuid": {uuid},
  "endDate": "2024-04-10T00:00:00.000Z",
  "headerImage": "",
  "title": "",
  "html": "",
  "status": "generating-proofs",
  "totalNumberAddresses": 10,
  "progress": 30,
  "root": "0xc75a0ece0abc4ce4ec70a78f6ee0d448d9845160f8e6265f3609998d9e38846c",
  "totalAmount": "7000000000000000000",
  "containsDuplicates": true
}

For larger claims (500,000 addresses or more) the generating proofs step may take some time, the progress can be checked by calling the endpoint above.

The root and uuid are needed to create a token claim on the hedgey contract.

const campaign = {
  id: '0x025f649ea6b44845875be9971b133e1e', // generated uuid as hex generated from the API
  contractAddress: '0x923b523B8cA37c5ea7BD990D1A98293495812Be6', // the token claim campaign address (Sepolia)
  manager: '0x0C4FAb8d9DBE774708EeC313bf0295278E307bcD', // the wallet address for the token claim manager (can cancel)
  token: '0xE13FB676E9bdd7AFda91495eC4e027FC63212FC3', // the token address
  amount: '8700000000', // amount of tokens
  start: '1719138856', // start date of the campaign in unix time
  end: '1712139217', // end date of the campaign in unix time
  tokenLockup: 0, // 0 unlocked, 1 locked, 2 vesting
  root: tree.root, // the root of the merkle tree generated from the API
  delegating: true, // if delegation is possible
}
const totalClaimers = 10;

const hash = await walletClient.writeContract({
  abi: claimCampaignAbi,
  address: campaign.contractAddress as `0x${string}`,
  functionName: 'createUnlockedCampaign',
  args: [
    id,
    {
      manager: campaign.manager,
      token: campaign.token,
      amount: campaign.amount,
      start: campaign.start,
      end: campaign.end,
      tokenLockup: campaign.tokenLockup,
      root: campaign.root,
      delegating: campaign.delegating,
    }
    totalClaimers: totalClaimers
  ],
  account: selectedAccount as `0x${string}`,
  chain,
  gas: gasEstimate,
});

Create locked claim

When users claim the tokens will be locked for a period of time, they will be receiving an NFT that gives the ability to unlock the tokens according to the vesting schedule.

const hash = await walletClient.writeContract({
    abi: delegatedClaimCampaign,
    address: campaign.contractAddress,
    functionName: 'createLockedCampaign',
    args: [
      id,
      {
        manager: campaign.manager,
        token: campaign.token,
        amount: BigInt(campaign.amount),
        start: BigInt(campaign.start),
        end: BigInt(campaign.end),
        tokenLockup: campaign.tokenLockup,
        root: campaign.root,
        delegating: campaign.delegating,
      },
      {
        tokenLocker: lockup.contractAddress,
        start: BigInt(getUnixTime(lockup.start)),
        cliff: BigInt(getUnixTime(lockup.cliff)),
        period: BigInt(lockup.period),
        periods: BigInt(lockup.periods),
      },
      campaign.vestingAdmin,
      BigInt(campaign.totalClaimers),
    ],
    account: selectedAccount,
    chain,
  });

Last updated