From 4932c36ea36f494d7eb135185473a69966ec16c6 Mon Sep 17 00:00:00 2001 From: Jagoda Berry Rybacka Date: Fri, 27 Oct 2023 13:06:26 +0200 Subject: [PATCH 01/10] Prepare xp utils for working with claims glossary --- .env.defaults | 1 + src/shared/contracts/xp.ts | 2 +- src/shared/types/xp.ts | 10 ++++-- src/shared/utils/xp.ts | 70 +++++++++++++++++++++++++++++++------- 4 files changed, 67 insertions(+), 16 deletions(-) diff --git a/.env.defaults b/.env.defaults index d29e521b2..c3d00ca0a 100644 --- a/.env.defaults +++ b/.env.defaults @@ -21,6 +21,7 @@ ALLOW_TENDERLY_RESET="false" ANALYTICS_ENV=DEV POSTHOG_API_KEY= # Misc +XP_HOSTING_BASE_URL="" # TBD SEASON_LENGTH_IN_WEEKS=8 CONTRACT_DEPLOYMENT_BLOCK_NUMBER=553443 SEASON_START_DATE="2023-10-26" diff --git a/src/shared/contracts/xp.ts b/src/shared/contracts/xp.ts index ca798eddd..776da039a 100644 --- a/src/shared/contracts/xp.ts +++ b/src/shared/contracts/xp.ts @@ -43,7 +43,7 @@ export const getUnclaimedXpDistributions: ReadTransactionBuilder< }, UnclaimedXpData[] > = async (provider, { realmId, account }) => { - const xpData = (await getXpDataForRealmId(realmId)) ?? [] + const xpData = await getXpDataForRealmId(realmId, account) const unclaimedOrNull = await Promise.all( xpData.map>( diff --git a/src/shared/types/xp.ts b/src/shared/types/xp.ts index 88d058c2f..e48cb4939 100644 --- a/src/shared/types/xp.ts +++ b/src/shared/types/xp.ts @@ -3,13 +3,17 @@ export type XpMerkleTreeItem = { amount: string proof: string[] } +export type XpMerkleTreeClaims = { + [address: string]: XpMerkleTreeItem +} export type XpMerkleTree = { totalAmount: string merkleRoot: string merkleDistributor: string - claims: { - [address: string]: XpMerkleTreeItem - } + claims: XpMerkleTreeClaims +} +export type XpMerkleTreeGlossary = Omit & { + glossary: { startAddress: string; file: string }[] } export type XpDistributor = { distributorContractAddress: string diff --git a/src/shared/utils/xp.ts b/src/shared/utils/xp.ts index 9ac70fcf0..a3c00fee4 100644 --- a/src/shared/utils/xp.ts +++ b/src/shared/utils/xp.ts @@ -1,8 +1,15 @@ import { LeaderboardItemData, XPLeaderboard } from "shared/types" -import { XpMerkleTree } from "shared/types/xp" +import { + XpMerkleTree, + XpMerkleTreeClaims, + XpMerkleTreeGlossary, +} from "shared/types/xp" import { isSameAddress, normalizeAddress } from "shared/utils/address" import XP_DATA from "../../assets/xp-data.json" +// eslint-disable-next-line prefer-destructuring +const XP_HOSTING_BASE_URL = process.env.XP_HOSTING_BASE_URL + type XpDataType = { [realmId: string]: { leaderboard: string | null; xp: string[] } } @@ -27,7 +34,9 @@ export async function getRealmLeaderboardData( // TODO: fix it - not working locally xpData = (await import(`${leaderboardUrl}`)).default } else { - xpData = await (await fetch(leaderboardUrl)).json() + xpData = await ( + await fetch(`${XP_HOSTING_BASE_URL}${leaderboardUrl}`) + ).json() } } catch (error) { // eslint-disable-next-line no-console @@ -39,41 +48,78 @@ export async function getRealmLeaderboardData( } export async function getXpDataForRealmId( - realmId: string -): Promise { + realmId: string, + account: string +): Promise { if (!realmId) { throw new Error("Missing realm id") } - let xpData: null | XpMerkleTree[] = null + const normalizedAddress = normalizeAddress(account) + + const targetAddress = BigInt(normalizedAddress) + let xpData: (null | XpMerkleTree)[] = [] try { const xpLinks = (XP_DATA as XpDataType)[realmId]?.xp if (!xpLinks || !xpLinks.length) { - return null + return [] } xpData = await Promise.all( xpLinks.map(async (url) => { - let data + let glossaryFile: XpMerkleTreeGlossary if (process.env.NODE_ENV === "development") { // TODO: fix it - not working locally - data = (await import(`${url}`)).default + glossaryFile = (await import(`${url}`)).default } else { - data = await (await fetch(url)).json() + glossaryFile = await ( + await fetch(`${XP_HOSTING_BASE_URL}${url}`) + ).json() + } + + if (!glossaryFile) { + throw new Error(`Failed to fetch glossaryFile from ${url}`) + } + + const claimLink = glossaryFile.glossary.find( + ({ startAddress }) => BigInt(startAddress ?? 0) >= targetAddress + )?.file + + if (!claimLink) { + throw new Error(`Failed to find claim link for ${normalizedAddress}`) + } + + const claims = (await ( + await fetch(`${XP_HOSTING_BASE_URL}${claimLink}`) + ).json()) as XpMerkleTreeClaims | undefined + + if (!claims) { + throw new Error(`Failed to fetch claims from ${claimLink}`) } - return data + const userClaim = claims[normalizedAddress] + + return userClaim + ? ({ + totalAmount: glossaryFile.totalAmount, + merkleRoot: glossaryFile.merkleRoot, + merkleDistributor: glossaryFile.merkleDistributor, + claims: { + [normalizedAddress]: userClaim, + }, + } as XpMerkleTree) + : null }) ) } catch (error) { // eslint-disable-next-line no-console - console.warn("No XP data found for the url:", realmId, error) + console.warn("No XP data found for the realm id:", realmId, error) } - return xpData + return xpData.flatMap((item) => (item ? [item] : [])) } export function getUserLeaderboardRank( From b3541f599b7bf2d68af151c91c833c8efbf7fd52 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Mon, 30 Oct 2023 09:31:40 +0100 Subject: [PATCH 02/10] Add module location information for dynamic import It is not possible to use a fully dynamic import statement. The import() must contain at least some information about where the module is located. --- src/shared/utils/xp.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/shared/utils/xp.ts b/src/shared/utils/xp.ts index 9ac70fcf0..4a5da149d 100644 --- a/src/shared/utils/xp.ts +++ b/src/shared/utils/xp.ts @@ -24,8 +24,11 @@ export async function getRealmLeaderboardData( return null } if (process.env.NODE_ENV === "development") { - // TODO: fix it - not working locally - xpData = (await import(`${leaderboardUrl}`)).default + xpData = ( + await import( + /* webpackInclude: /\.json$/ */ `../../../src${leaderboardUrl}` + ) + ).default } else { xpData = await (await fetch(leaderboardUrl)).json() } @@ -59,8 +62,9 @@ export async function getXpDataForRealmId( let data if (process.env.NODE_ENV === "development") { - // TODO: fix it - not working locally - data = (await import(`${url}`)).default + data = ( + await import(/* webpackInclude: /\.json$/ */ `../../../src${url}`) + ).default } else { data = await (await fetch(url)).json() } From 3f2618d4b629ec2303eeb4c26b055369c3824377 Mon Sep 17 00:00:00 2001 From: Jagoda Berry Rybacka Date: Mon, 30 Oct 2023 14:01:29 +0100 Subject: [PATCH 03/10] Create XP drops folder structure --- src/assets/xp-data.json | 52 +++++++++++-------- .../xp => assets/xp/arbitrum/claims}/.keep | 0 src/assets/xp/cyberconnect/claims/.keep | 0 src/assets/xp/frax/claims/.keep | 0 src/assets/xp/galxe/claims/.keep | 0 src/assets/xp/gitcoin/claims/.keep | 0 6 files changed, 31 insertions(+), 21 deletions(-) rename src/{data/xp => assets/xp/arbitrum/claims}/.keep (100%) create mode 100644 src/assets/xp/cyberconnect/claims/.keep create mode 100644 src/assets/xp/frax/claims/.keep create mode 100644 src/assets/xp/galxe/claims/.keep create mode 100644 src/assets/xp/gitcoin/claims/.keep diff --git a/src/assets/xp-data.json b/src/assets/xp-data.json index bcac8addb..b79a2797e 100644 --- a/src/assets/xp-data.json +++ b/src/assets/xp-data.json @@ -1,22 +1,32 @@ { - "4": { - "xp": [], - "leaderboard": null - }, - "7": { - "xp": [], - "leaderboard": null - }, - "9": { - "xp": [], - "leaderboard": null - }, - "19": { - "xp": [], - "leaderboard": null - }, - "22": { - "xp": [], - "leaderboard": null - } -} \ No newline at end of file + "4": { + "rootFolder": "/assets/xp/gitcoin", + "claimsFolder": "/assets/xp/gitcoin/claims", + "xpGlossary": [], + "leaderboard": null + }, + "7": { + "rootFolder": "/assets/xp/cyberconnect", + "claimsFolder": "/assets/xp/cyberconnect/claims", + "xpGlossary": [], + "leaderboard": null + }, + "9": { + "rootFolder": "/assets/xp/arbitrum", + "claimsFolder": "/assets/xp/arbitrum/claims", + "xpGlossary": [], + "leaderboard": null + }, + "19": { + "rootFolder": "/assets/xp/galxe", + "claimsFolder": "/assets/xp/galxe/claims", + "xpGlossary": [], + "leaderboard": null + }, + "22": { + "rootFolder": "/assets/xp/frax", + "claimsFolder": "/assets/xp/frax/claims", + "xpGlossary": [], + "leaderboard": null + } +} diff --git a/src/data/xp/.keep b/src/assets/xp/arbitrum/claims/.keep similarity index 100% rename from src/data/xp/.keep rename to src/assets/xp/arbitrum/claims/.keep diff --git a/src/assets/xp/cyberconnect/claims/.keep b/src/assets/xp/cyberconnect/claims/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/src/assets/xp/frax/claims/.keep b/src/assets/xp/frax/claims/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/src/assets/xp/galxe/claims/.keep b/src/assets/xp/galxe/claims/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/src/assets/xp/gitcoin/claims/.keep b/src/assets/xp/gitcoin/claims/.keep new file mode 100644 index 000000000..e69de29bb From 5cbf8b6bec872a5e01559cc6a425a3599b58a0fb Mon Sep 17 00:00:00 2001 From: Jagoda Berry Rybacka Date: Mon, 30 Oct 2023 14:02:38 +0100 Subject: [PATCH 04/10] Fix again fetching XP drop files locally Provide more details abou file path for webpack. Cleanup code. --- src/shared/utils/xp.ts | 145 ++++++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 60 deletions(-) diff --git a/src/shared/utils/xp.ts b/src/shared/utils/xp.ts index a9c00a903..7d0e59ea0 100644 --- a/src/shared/utils/xp.ts +++ b/src/shared/utils/xp.ts @@ -11,7 +11,31 @@ import XP_DATA from "../../assets/xp-data.json" const XP_HOSTING_BASE_URL = process.env.XP_HOSTING_BASE_URL type XpDataType = { - [realmId: string]: { leaderboard: string | null; xp: string[] } + [realmId: string]: { + rootFolder?: string + claimsFolder?: string + leaderboard: string | null + xpGlossary: string[] + } +} + +async function fetchOrImport(url: string) { + if (process.env.NODE_ENV === "development") { + // We need to give webpack a hint where these files are located in the filesystem + // so we remove parts of the path and file extension - including this directly in a dynamic import + // string template will make webpack include all files in the bundle + const fileWithoutExtension = url + .replace("/assets/xp/", "") + .replace(/.json$/, "") + return ( + await import( + /* webpackInclude: /\.json$/ */ `../../../src/assets/xp/${fileWithoutExtension}.json` + ) + ).default + } + // For production we fetch the data from the XP hosting server - by default we can use + // json files from "assets" folder as they are copied to the build folder during the build process + return (await fetch(`${XP_HOSTING_BASE_URL}${url}`)).json() } export async function getRealmLeaderboardData( @@ -21,33 +45,30 @@ export async function getRealmLeaderboardData( throw new Error("Missing realm id") } - let xpData: null | XPLeaderboard = null + const xpData = (XP_DATA as XpDataType)[realmId] - if (realmId) { - try { - const leaderboardUrl = (XP_DATA as XpDataType)[realmId]?.leaderboard + if (!xpData) { + throw new Error("Missing data in xp-data.json") + } - if (!leaderboardUrl) { - return null - } - if (process.env.NODE_ENV === "development") { - xpData = ( - await import( - /* webpackInclude: /\.json$/ */ `../../../src${leaderboardUrl}` - ) - ).default - } else { - xpData = await ( - await fetch(`${XP_HOSTING_BASE_URL}${leaderboardUrl}`) - ).json() - } - } catch (error) { - // eslint-disable-next-line no-console - console.warn("No XP data found for the realm id:", realmId, error) - } + let leaderboardData: null | XPLeaderboard = null + + const { rootFolder, leaderboard } = xpData + + if (!rootFolder || !leaderboard) { + return null + } + + const leaderboardUrl = `${rootFolder}/${leaderboard}` + + try { + leaderboardData = await fetchOrImport(leaderboardUrl) + } catch (error) { + // eslint-disable-next-line no-console + console.warn("No leaderboard data found for the realm id:", realmId, error) } - return xpData + return leaderboardData } export async function getXpDataForRealmId( @@ -61,44 +82,45 @@ export async function getXpDataForRealmId( const normalizedAddress = normalizeAddress(account) const targetAddress = BigInt(normalizedAddress) - let xpData: (null | XpMerkleTree)[] = [] + let claimsData: (null | XpMerkleTree)[] = [] + + const xpData = (XP_DATA as XpDataType)[realmId] try { - const xpLinks = (XP_DATA as XpDataType)[realmId]?.xp + const { rootFolder, claimsFolder, xpGlossary } = xpData - if (!xpLinks || !xpLinks.length) { + if (!rootFolder || !claimsFolder || !xpGlossary || !xpGlossary.length) { return [] } - xpData = await Promise.all( - xpLinks.map(async (url) => { - let glossaryFile: XpMerkleTreeGlossary - - if (process.env.NODE_ENV === "development") { - glossaryFile = ( - await import(/* webpackInclude: /\.json$/ */ `../../../src${url}`) - ).default - } else { - glossaryFile = await ( - await fetch(`${XP_HOSTING_BASE_URL}${url}`) - ).json() - } + claimsData = await Promise.all( + xpGlossary.map(async (file) => { + const glossaryUrl = `${rootFolder}/${file}` + + const glossaryFile: XpMerkleTreeGlossary = await fetchOrImport( + glossaryUrl + ) if (!glossaryFile) { - throw new Error(`Failed to fetch glossaryFile from ${url}`) + throw new Error(`Failed to fetch glossaryFile from ${glossaryUrl}`) } - const claimLink = glossaryFile.glossary.find( - ({ startAddress }) => BigInt(startAddress ?? 0) >= targetAddress - )?.file + const claimFileIndex = + glossaryFile.glossary.findIndex( + ({ startAddress }) => BigInt(startAddress ?? 0) > targetAddress + ) - 1 + const claimFile = glossaryFile.glossary[claimFileIndex]?.file - if (!claimLink) { - throw new Error(`Failed to find claim link for ${normalizedAddress}`) + if (!claimFile) { + // No claim file found for the user + return null } - const claims = (await ( - await fetch(`${XP_HOSTING_BASE_URL}${claimLink}`) - ).json()) as XpMerkleTreeClaims | undefined + const claimLink = `${claimsFolder}/${claimFile}` + + const claims: XpMerkleTreeClaims | undefined = await fetchOrImport( + claimLink + ) if (!claims) { throw new Error(`Failed to fetch claims from ${claimLink}`) @@ -106,16 +128,19 @@ export async function getXpDataForRealmId( const userClaim = claims[normalizedAddress] - return userClaim - ? ({ - totalAmount: glossaryFile.totalAmount, - merkleRoot: glossaryFile.merkleRoot, - merkleDistributor: glossaryFile.merkleDistributor, - claims: { - [normalizedAddress]: userClaim, - }, - } as XpMerkleTree) - : null + if (userClaim) { + return { + totalAmount: glossaryFile.totalAmount, + merkleRoot: glossaryFile.merkleRoot, + merkleDistributor: glossaryFile.merkleDistributor, + claims: { + [normalizedAddress]: userClaim, + }, + } as XpMerkleTree + } + + // No claim found for the user + return null }) ) } catch (error) { @@ -123,7 +148,7 @@ export async function getXpDataForRealmId( console.warn("No XP data found for the realm id:", realmId, error) } - return xpData.flatMap((item) => (item ? [item] : [])) + return claimsData.flatMap((item) => (item ? [item] : [])) } export function getUserLeaderboardRank( From 6669e323f702f8991415b01ebd47e321d5bf2813 Mon Sep 17 00:00:00 2001 From: Jagoda Berry Rybacka Date: Mon, 30 Oct 2023 14:02:52 +0100 Subject: [PATCH 05/10] Docs about XP distribution --- docs/xp-distribution.md | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 docs/xp-distribution.md diff --git a/docs/xp-distribution.md b/docs/xp-distribution.md new file mode 100644 index 000000000..a6710ff4e --- /dev/null +++ b/docs/xp-distribution.md @@ -0,0 +1,51 @@ +# XP distribution + +### On chain allocation + +Allocation is done using the script from the `[contracts](https://github.com/tahowallet/contracts)` repository, please use documentation written for the script there. This documentation assumes you've already generated all the files and the drop already happened. The only thing left to do is to provide the dapp source merkle tree data for given allocation. + +### Providing XP data in the dapp + +1. In the `src/assets/xp-data.json` find out where is the folder for the realm that you did the XP drop on. Should be `assets/xp//` + +Update leaderboard + +2. Copy the `leaderboard.json` file from `contracts` repo that was just created by the allocation script. + +3. If we already had leaderbord file (`assets/xp//leaderboard.json`) then let's replace the leaderboard file with the new one. Leaderboard data will sum xp amounts from previous drops so it should be replaced with updated data. + +4. In the `src/assets/xp-data.json` make sure leaderboard file name got updated if needed. If this is the first drop on a given realm then please update it to (`leaderboard` field): +```json + "": { + "rootFolder": "/assets/xp/", + "claimsFolder": "/assets/xp//claims", + "xpGlossary": [], + "leaderboard": "leaderboard.json" + }, +``` + +Upload XP drop glossary + +5. Copy the main file with XP drop data from the contracts. Make sure this is correct file - it should contain `glossary` field and `merkleDistributor` + +6. Paste that file into `assets/xp//` folder + +7. Update `src/assets/xp-data.json` with the glossary file name (`xpGlossary` field). If this is first drop then the `xpGlossary` array will be empty, if not then add new file name to the end of the array. Each file is named with the merkle root value. +```json + "": { + "rootFolder": "/assets/xp/", + "claimsFolder": "/assets/xp//claims", + "xpGlossary": ["0x.json", "0x.json"], + "leaderboard": "leaderboard.json" + }, +``` + +Upload XP claim files + +8. Copy all files from the `contracts` repo that were created in the `claims` folder for a given XP drop +9. Paste them into the `"src/assets/xp//claims` folder. Don't remove existing files if this is not the first drop. +10. Look into the glossary file (`/assets/xp//0x.json`) and confirm it is referring to the same files you just pasted into the `claims` folder. + +Testing + +11. Run app locally or build it on Netlify PR preview to make sure you can see correct XP values in the claim banner and XP leaderboard. Confirm you are able to claim XP if possible on a given environment. From db6fb3d01c5b460da16d16117bee62a47bb00cb4 Mon Sep 17 00:00:00 2001 From: Jagoda Rybacka Date: Mon, 30 Oct 2023 14:27:29 +0100 Subject: [PATCH 06/10] Fix link in the markdown --- docs/xp-distribution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/xp-distribution.md b/docs/xp-distribution.md index a6710ff4e..67869c74f 100644 --- a/docs/xp-distribution.md +++ b/docs/xp-distribution.md @@ -2,7 +2,7 @@ ### On chain allocation -Allocation is done using the script from the `[contracts](https://github.com/tahowallet/contracts)` repository, please use documentation written for the script there. This documentation assumes you've already generated all the files and the drop already happened. The only thing left to do is to provide the dapp source merkle tree data for given allocation. +Allocation is done using the script from the [contracts](https://github.com/tahowallet/contracts) repository, please use documentation written for the script there. This documentation assumes you've already generated all the files and the drop already happened. The only thing left to do is to provide the dapp source merkle tree data for given allocation. ### Providing XP data in the dapp From 939cec5a0d140a9df0a967079b9b1b9adedb7597 Mon Sep 17 00:00:00 2001 From: Jagoda Berry Rybacka Date: Tue, 31 Oct 2023 11:24:42 +0100 Subject: [PATCH 07/10] Refactor fetching leaderboard data --- src/shared/utils/xp.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/shared/utils/xp.ts b/src/shared/utils/xp.ts index 7d0e59ea0..f22301326 100644 --- a/src/shared/utils/xp.ts +++ b/src/shared/utils/xp.ts @@ -51,8 +51,6 @@ export async function getRealmLeaderboardData( throw new Error("Missing data in xp-data.json") } - let leaderboardData: null | XPLeaderboard = null - const { rootFolder, leaderboard } = xpData if (!rootFolder || !leaderboard) { @@ -62,13 +60,13 @@ export async function getRealmLeaderboardData( const leaderboardUrl = `${rootFolder}/${leaderboard}` try { - leaderboardData = await fetchOrImport(leaderboardUrl) + return await fetchOrImport(leaderboardUrl) } catch (error) { // eslint-disable-next-line no-console console.warn("No leaderboard data found for the realm id:", realmId, error) - } - return leaderboardData + return null + } } export async function getXpDataForRealmId( From b898c46e9b4313c753885951af3032b5afa5d43b Mon Sep 17 00:00:00 2001 From: Jagoda Berry Rybacka Date: Tue, 31 Oct 2023 11:26:21 +0100 Subject: [PATCH 08/10] Add link to scripts documentation --- docs/xp-distribution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/xp-distribution.md b/docs/xp-distribution.md index 67869c74f..0d034721b 100644 --- a/docs/xp-distribution.md +++ b/docs/xp-distribution.md @@ -2,7 +2,7 @@ ### On chain allocation -Allocation is done using the script from the [contracts](https://github.com/tahowallet/contracts) repository, please use documentation written for the script there. This documentation assumes you've already generated all the files and the drop already happened. The only thing left to do is to provide the dapp source merkle tree data for given allocation. +Allocation is done using the script from the [contracts](https://github.com/tahowallet/contracts) repository, please use [documentation](https://github.com/tahowallet/contracts/blob/main/merkle/README.adoc) written for the script there. This documentation assumes you've already generated all the files and the drop already happened. The only thing left to do is to provide the dapp source merkle tree data for given allocation. ### Providing XP data in the dapp From e95ff0f27acca186ae8008aa0777af237d833143 Mon Sep 17 00:00:00 2001 From: Jagoda Berry Rybacka Date: Tue, 31 Oct 2023 12:05:49 +0100 Subject: [PATCH 09/10] Fix finding claim file index and add doc comment --- src/shared/utils/xp.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/shared/utils/xp.ts b/src/shared/utils/xp.ts index f22301326..b35e26a45 100644 --- a/src/shared/utils/xp.ts +++ b/src/shared/utils/xp.ts @@ -103,10 +103,21 @@ export async function getXpDataForRealmId( throw new Error(`Failed to fetch glossaryFile from ${glossaryUrl}`) } + // Addresses in the claim files are sorted in ascending order, + // we only know about the address that the file starts with and our `targetAddress`. + // * If `startAddress` < `targetAddress` then we don't know if the address + // is in the current claim file or the next one. We assume that it's in the one of the upcoming files. + // * If `startAddress` > `targetAddress` then we know that the address is in the previous file. + // Edge cases are: + // * `targetAddress` === `startAddress` - this is covered by the same logic as the regular case, + // becuase we will come back to the previous file, because while cheking next claim file startAddress > targetAddress + // * `targetAddress` is in the first file - this is covered by defaulting to the first file is none of the files match + // * `targetAddress` is not in the drop at all - not a problem, we will return null + const suspectedNextClaimFileIndex = glossaryFile.glossary.findIndex( + ({ startAddress }) => BigInt(startAddress ?? 0) > targetAddress + ) const claimFileIndex = - glossaryFile.glossary.findIndex( - ({ startAddress }) => BigInt(startAddress ?? 0) > targetAddress - ) - 1 + suspectedNextClaimFileIndex <= 0 ? 0 : suspectedNextClaimFileIndex - 1 const claimFile = glossaryFile.glossary[claimFileIndex]?.file if (!claimFile) { From ac6dfa110e1ad2f535c32a700dd8332d0b325ec2 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Tue, 31 Oct 2023 12:22:50 +0100 Subject: [PATCH 10/10] Minor fix for fetching claims data --- src/shared/utils/xp.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/utils/xp.ts b/src/shared/utils/xp.ts index b35e26a45..ea77da207 100644 --- a/src/shared/utils/xp.ts +++ b/src/shared/utils/xp.ts @@ -110,7 +110,7 @@ export async function getXpDataForRealmId( // * If `startAddress` > `targetAddress` then we know that the address is in the previous file. // Edge cases are: // * `targetAddress` === `startAddress` - this is covered by the same logic as the regular case, - // becuase we will come back to the previous file, because while cheking next claim file startAddress > targetAddress + // because we will come back to the previous file, because while checking next claim file startAddress > targetAddress // * `targetAddress` is in the first file - this is covered by defaulting to the first file is none of the files match // * `targetAddress` is not in the drop at all - not a problem, we will return null const suspectedNextClaimFileIndex = glossaryFile.glossary.findIndex( @@ -125,7 +125,7 @@ export async function getXpDataForRealmId( return null } - const claimLink = `${claimsFolder}/${claimFile}` + const claimLink = `${claimsFolder}${claimFile}` const claims: XpMerkleTreeClaims | undefined = await fetchOrImport( claimLink