diff --git a/action/index.cjs b/action/index.cjs index 7f45025..5cf0832 100644 --- a/action/index.cjs +++ b/action/index.cjs @@ -188028,9 +188028,16 @@ const robot = (app) => { const allOwnersToCheck = [mainOwner, ...extraOwners]; const apiUrl = getApiUrl(); for (const owner of allOwnersToCheck) { + const alreadyExistingBranding = await isProviderAlreadyBranded(apiUrl, asset, owner); + if (alreadyExistingBranding && alreadyExistingBranding.existing && !alreadyExistingBranding.isUpdate) { + await fail(`${owner} is already branded. Only updates are allowed.`); + return []; + } if (new out_1.Address(owner).isContractAddress()) { - const ownerResult = await axios_1.default.get(`${apiUrl}/accounts/${owner}?extract=ownerAddress`); - allOwners.push(ownerResult.data); + const ownerResult = await fetchStringValueFromApi(apiUrl, "accounts", owner, "ownerAddress"); + if (ownerResult) { + allOwners.push(ownerResult); + } } else { allOwners.push(owner); @@ -188038,6 +188045,25 @@ const robot = (app) => { } return [...new Set(allOwners)]; } + async function isProviderAlreadyBranded(apiUrl, identity, provider) { + try { + const providerInfo = await axios_1.default.get(`${apiUrl}/providers/${provider}`); + if (!providerInfo) { + return { existing: false }; + } + if (!providerInfo.data?.identity) { + return { existing: false }; + } + return { + existing: true, + isUpdate: identity === providerInfo.data?.identity, + }; + } + catch (error) { + console.error(`API error while fetching the provider data for address ${provider}: ${error}`); + return { existing: false }; + } + } async function getAccountOwner(account) { const accountOwner = account; if (new out_1.Address(accountOwner).isContractAddress()) { @@ -188047,11 +188073,7 @@ const robot = (app) => { } async function getAccountOwnerFromApi(address) { const apiUrl = getApiUrl(); - const accountOwnerResponse = await axios_1.default.get(`${apiUrl}/accounts/${address}?extract=ownerAddress`); - if (accountOwnerResponse && accountOwnerResponse.data) { - return accountOwnerResponse.data; - } - return ''; + return await fetchStringValueFromApi(apiUrl, "accounts", address, "ownerAddress"); } async function getTokenOwner(token) { // since the token owner can be changed at protocol level at any time, it's enough to check the ownership of the token, @@ -188059,17 +188081,27 @@ const robot = (app) => { const apiUrl = getApiUrl(); const tokenOwner = await getTokenOwnerFromApi(token, apiUrl); if (new out_1.Address(tokenOwner).isContractAddress()) { - const ownerResult = await axios_1.default.get(`${apiUrl}/accounts/${tokenOwner}?extract=ownerAddress`); - return ownerResult.data; + return await fetchStringValueFromApi(apiUrl, "accounts", tokenOwner, "ownerAddress"); } return tokenOwner; } async function getTokenOwnerFromApi(token, apiUrl) { - const tokenOwnerResponse = await axios_1.default.get(`${apiUrl}/tokens/${token}?extract=owner`); - if (tokenOwnerResponse && tokenOwnerResponse.data) { - return tokenOwnerResponse.data; + return await fetchStringValueFromApi(apiUrl, "tokens", token, "owner") || + await fetchStringValueFromApi(apiUrl, "collections", token, "owner"); + } + async function fetchStringValueFromApi(apiUrl, endpoint, query, extract) { + let requestUrl = `${apiUrl}/${endpoint}/${query}`; + if (extract) { + requestUrl += `?extract=${extract}`; + } + try { + const response = await axios_1.default.get(requestUrl); + return response.data; + } + catch (error) { + console.error(`Cannot query API at ${requestUrl}: ${error}`); + return ''; } - return ''; } function getApiUrl() { switch (network) { diff --git a/src/bot.ts b/src/bot.ts index 51d5124..5851d35 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -66,9 +66,16 @@ export const robot = (app: Probot) => { const apiUrl = getApiUrl(); for (const owner of allOwnersToCheck) { + const alreadyExistingBranding = await isProviderAlreadyBranded(apiUrl, asset as string, owner); + if (alreadyExistingBranding && alreadyExistingBranding.existing && !alreadyExistingBranding.isUpdate) { + await fail(`${owner} is already branded. Only updates are allowed.`); + return []; + } if (new Address(owner).isContractAddress()) { - const ownerResult = await axios.get(`${apiUrl}/accounts/${owner}?extract=ownerAddress`); - allOwners.push(ownerResult.data); + const ownerResult = await fetchStringValueFromApi(apiUrl, "accounts", owner, "ownerAddress"); + if (ownerResult) { + allOwners.push(ownerResult); + } } else { allOwners.push(owner); } @@ -77,6 +84,30 @@ export const robot = (app: Probot) => { return [...new Set(allOwners)]; } + async function isProviderAlreadyBranded(apiUrl: string, identity: string, provider: string): Promise<{ + existing: boolean, + isUpdate?: boolean + }> { + try { + const providerInfo = await axios.get(`${apiUrl}/providers/${provider}`); + if (!providerInfo) { + return { existing: false }; + } + + if (!providerInfo.data?.identity) { + return { existing: false }; + } + + return { + existing: true, + isUpdate: identity === providerInfo.data?.identity, + }; + } catch (error) { + console.error(`API error while fetching the provider data for address ${provider}: ${error}`); + return { existing: false }; + } + } + async function getAccountOwner(account: string): Promise { const accountOwner = account; if (new Address(accountOwner).isContractAddress()) { @@ -88,12 +119,7 @@ export const robot = (app: Probot) => { async function getAccountOwnerFromApi(address: string): Promise { const apiUrl = getApiUrl(); - const accountOwnerResponse = await axios.get(`${apiUrl}/accounts/${address}?extract=ownerAddress`); - if (accountOwnerResponse && accountOwnerResponse.data) { - return accountOwnerResponse.data; - } - - return ''; + return await fetchStringValueFromApi(apiUrl, "accounts", address, "ownerAddress"); } async function getTokenOwner(token: string): Promise { @@ -103,20 +129,29 @@ export const robot = (app: Probot) => { const tokenOwner = await getTokenOwnerFromApi(token, apiUrl); if (new Address(tokenOwner).isContractAddress()) { - const ownerResult = await axios.get(`${apiUrl}/accounts/${tokenOwner}?extract=ownerAddress`); - return ownerResult.data; + return await fetchStringValueFromApi(apiUrl, "accounts", tokenOwner, "ownerAddress"); } return tokenOwner; } async function getTokenOwnerFromApi(token: string, apiUrl: string): Promise { - const tokenOwnerResponse = await axios.get(`${apiUrl}/tokens/${token}?extract=owner`); - if (tokenOwnerResponse && tokenOwnerResponse.data) { - return tokenOwnerResponse.data; - } + return await fetchStringValueFromApi(apiUrl, "tokens", token, "owner") || + await fetchStringValueFromApi(apiUrl, "collections", token, "owner"); + } - return ''; + async function fetchStringValueFromApi(apiUrl: string, endpoint: string, query: string, extract?: string): Promise { + let requestUrl = `${apiUrl}/${endpoint}/${query}`; + if (extract) { + requestUrl += `?extract=${extract}`; + } + try { + const response = await axios.get(requestUrl); + return response.data; + } catch (error) { + console.error(`Cannot query API at ${requestUrl}: ${error}`); + return ''; + } } function getApiUrl() {