Examples of common flows
Here are common architectural flows you may need to integrate into your application. These include methods to gather prerequisite data for each backend functionality described earlier.
Get a campaign's CID
To obtain a campaign's IPFS CID, you can:
Check the create events emitted by the Merkle factory
- Use the Sablier indexers to query for that information.
For approach "B", run the following query against the official endpoints:
- The Graph
- Envio
query getCampaignData($campaignId: String!){
campaign(id: $campaignId){
id
lockup
root
ipfsCID
aggregateAmount
totalRecipients
}
}
query getCampaignData($campaignId: String!){
Campaign(where: {id: {_eq: $campaignId}} ){
id
lockup
root
ipfsCID
aggregateAmount
totalRecipients
}
}
Check eligibility for an address
To check if an address is eligible, use the /api/eligibility route provided by the merkle-api backend.
Steps
- Get the campaign CID (see the example above)
- Call the
/api/eligibility
route using the CID and wallet address
Read more in the dedicated route documentation within the /api/eligibility section of the functionality page.
Alternatively, you can check eligibility by searching for the address in the list stored within the IPFS file from step 1. You'll still need to download the file first using its CID.
Get the tokenId
after a claim
After someone claims, you may want to show them a preview of the stream or its NFT. To do this, you'll need the tokenId
(or streamId
) related to that user's claim.
To obtain a tokenId
linked to a claim, you can:
Listen to the claim method and the Claim event emitted by the Merkle contract instance
- Use the Sablier Indexers to query for that information.
For approach "B", run the following query against the official endpoints (ensure the address is lowercase):
- The Graph
- Envio
query getClaimForRecipient($campaignId: String!, $recipient: String) {
actions(where: { campaign: $campaignId, category: Claim, claimRecipient: $recipient }) {
campaign {
id
lockup
}
claimTokenId
claimRecipient
claimIndex
}
}
query getClaimForRecipient($campaignId: String!, $recipient: String) {
Action(
where: {
_and: [{ campaign: { _eq: $campaignId } }, { category: { _eq: Claim } }, { claimRecipient: { _eq: $recipient } }]
}
) {
campaignObject {
id
lockup
}
claimTokenId
claimRecipient
claimIndex
}
}
Bonus: Stream NFT
To get the Stream NFT, use the same query as option "B" to retrieve the lockup
contract (where the Stream NFT is issued) and its tokenId
. With these, you can call the tokenURI
method, which returns the SVG code of the onchain NFT.
The actual SVG tags are encoded inside the tokenURI
method response. You can feed this blob to an HTML img
tag or render the SVG tags directly. To extract this code in plain format (not base64
), run the following JavaScript code to decode the response:
const toPart = output.split("data:application/json;base64,").pop();
const toString = Buffer.from(toPart || "", "base64").toString("utf-8");
const toJSON = JSON.parse(toString);
const blob = _.get(toJSON, "image")?.split("data:image/svg+xml;base64,")[1];
const toSVG = Buffer.from(blob || "", "base64").toString("utf-8");
Check if a user claimed their stream
To check if a user has already claimed their stream from a campaign, you can:
Call the
hasClaimed
method from the Merkle contract instance- Use the Sablier Indexers to query for that information.
Approach A
For approach "A", perform the following actions:
- Get the campaign's CID, Lockup contract address, and user address (for the first items, see the Get a campaign's CID example above)
- Check user eligibility (see Eligibility example above) and extract their
index
- Call the
hasClaimed
method inside thelockup
contract using theindex
from step 2
A user's index represents their assigned order number in the eligibility list. We use this value to generate a proof if the recipient is eligible and to register their claim directly in the contract.
Approach B
For approach "B", run the same query as in the Get the tokenId after a claim example. If the query returns results, the user has claimed their stream.
A missing claim could also mean the user wasn't eligible initially. We recommend checking for eligibility alongside any existing claim checks.