Skip to content

Commit 9b75502

Browse files
committed
feat(scripts): implement sales values updater for Hypercerts
- this script will retroactively update existing rows in the sales table of supabase to contain fee_amounts, fee_recipients and currency_amount - it will also update any hypercert_id's that erronously ended up with an 'undefined' for the token ID
1 parent 3eb856b commit 9b75502

File tree

1 file changed

+187
-0
lines changed

1 file changed

+187
-0
lines changed

scripts/update_sales_values.ts

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
import "dotenv/config";
2+
3+
import { createClient } from "@supabase/supabase-js";
4+
import { parseClaimOrFractionId } from "@hypercerts-org/sdk";
5+
import { createPublicClient, erc20Abi, zeroAddress } from "viem";
6+
import { http } from "viem";
7+
import {
8+
arbitrum,
9+
arbitrumSepolia,
10+
base,
11+
baseSepolia,
12+
celo,
13+
filecoin,
14+
filecoinCalibration,
15+
optimism,
16+
} from "viem/chains";
17+
import { Chain } from "viem";
18+
import { sepolia } from "viem/chains";
19+
import { HypercertMinterAbi } from "@hypercerts-org/sdk";
20+
import { parseEventLogs } from "viem";
21+
import { TakerBid } from "../src/storage/storeTakerBid.js";
22+
import { getAddress } from "viem";
23+
import { getDeployment } from "../src/utils/getDeployment.js";
24+
import { getHypercertTokenId } from "../src/utils/tokenIds.js";
25+
import { HypercertExchangeAbi } from "@hypercerts-org/sdk";
26+
import { EvmClientFactory } from "../src/clients/evmClient.js";
27+
28+
const getChain = (chainId: number) => {
29+
const chains: Record<number, Chain> = {
30+
10: optimism,
31+
314: filecoin,
32+
8453: base,
33+
42161: arbitrum,
34+
42220: celo,
35+
84532: baseSepolia,
36+
314159: filecoinCalibration,
37+
421614: arbitrumSepolia,
38+
11155111: sepolia,
39+
};
40+
41+
const chain = chains[chainId];
42+
if (!chain) throw new Error(`Unsupported chain ID: ${chainId}`);
43+
return chain;
44+
};
45+
46+
const main = async () => {
47+
console.log("update_sales_values");
48+
// Get all sales rows
49+
// Create supabase client
50+
const supabase = createClient(
51+
process.env.SUPABASE_CACHING_DB_URL!,
52+
process.env.SUPABASE_CACHING_SERVICE_API_KEY!,
53+
);
54+
const salesResponse = await supabase.from("sales").select("*");
55+
const sales = salesResponse.data;
56+
57+
if (!sales) {
58+
console.log("No sales found");
59+
return;
60+
}
61+
62+
const results: TakerBid[] = [];
63+
for (const sale of sales) {
64+
let chainId: number | undefined;
65+
const tokenId = BigInt(sale.item_ids[0]);
66+
const claimId = getHypercertTokenId(tokenId);
67+
const hypercert_id = sale.hypercert_id.replace("undefined", claimId);
68+
69+
try {
70+
chainId = parseClaimOrFractionId(hypercert_id).chainId;
71+
if (!chainId) {
72+
console.log("No chainId found for sale", sale);
73+
continue;
74+
}
75+
} catch (e) {
76+
console.log("Error parsing hypercert_id", hypercert_id);
77+
continue;
78+
}
79+
// Get transaction and parse logs using viem
80+
81+
const client = EvmClientFactory.createClient(Number(chainId));
82+
const { addresses } = getDeployment(Number(chainId));
83+
const { currency } = sale;
84+
85+
try {
86+
const transactionReceipt = await client.getTransactionReceipt({
87+
hash: sale.transaction_hash as `0x${string}`,
88+
});
89+
90+
// parse logs to get claimID, contractAddress and cid
91+
const transactionLogsHypercertMinter = transactionReceipt.logs.filter(
92+
(log) =>
93+
log.address.toLowerCase() ===
94+
addresses?.HypercertMinterUUPS?.toLowerCase(),
95+
);
96+
97+
let currencyAmount = 0n;
98+
if (currency === zeroAddress) {
99+
// Get value of the transaction
100+
const transaction = await client.getTransaction({
101+
hash: sale.transaction_hash as `0x${string}`,
102+
});
103+
currencyAmount = transaction.value;
104+
} else {
105+
const currencyLogs = transactionReceipt.logs.filter(
106+
(log) => log.address.toLowerCase() === currency.toLowerCase(),
107+
);
108+
const parsedCurrencyLogs = parseEventLogs({
109+
abi: erc20Abi,
110+
logs: currencyLogs,
111+
});
112+
const transferLog = parsedCurrencyLogs.find(
113+
(log) => log.eventName === "Transfer",
114+
);
115+
currencyAmount = transferLog?.args?.value ?? 0n;
116+
}
117+
118+
const exchangeLogs = transactionReceipt.logs.filter(
119+
(log) =>
120+
log.address.toLowerCase() ===
121+
addresses?.HypercertExchange?.toLowerCase(),
122+
);
123+
124+
const parsedExchangeLog = parseEventLogs({
125+
abi: HypercertExchangeAbi,
126+
logs: exchangeLogs,
127+
// @ts-expect-error eventName is missing in the type
128+
}).find((log) => log.eventName === "TakerBid");
129+
130+
// @ts-expect-error args is missing in the type
131+
const fee_amounts = parsedExchangeLog?.args?.feeAmounts;
132+
// @ts-expect-error args is missing in the type
133+
const fee_recipients = parsedExchangeLog?.args?.feeRecipients;
134+
135+
results.push(
136+
TakerBid.parse({
137+
amounts: sale.amounts.map((amount) => BigInt(amount)),
138+
seller: getAddress(sale.seller),
139+
buyer: getAddress(sale.buyer),
140+
currency: getAddress(sale.currency),
141+
collection: getAddress(sale.collection),
142+
item_ids: sale.item_ids.map((item_id) => BigInt(item_id)),
143+
strategy_id: BigInt(sale.strategy_id),
144+
hypercert_id: hypercert_id,
145+
transaction_hash: sale.transaction_hash,
146+
currency_amount: currencyAmount,
147+
fee_amounts: fee_amounts,
148+
fee_recipients: fee_recipients,
149+
}),
150+
);
151+
} catch (e) {
152+
console.log("Error parsing transaction", JSON.stringify(sale, null, 2));
153+
console.log(e);
154+
continue;
155+
}
156+
}
157+
158+
// Combine parsed results with original sales data by matching transaction hashes
159+
const rowsToUpsert = results.map((result) => {
160+
const originalSale = sales.find(
161+
(sale) => sale.transaction_hash === result.transaction_hash,
162+
);
163+
if (!originalSale) {
164+
throw new Error(
165+
`Could not find original sale for transaction ${result.transaction_hash}`,
166+
);
167+
}
168+
return {
169+
...originalSale,
170+
...result,
171+
strategy_id: result.strategy_id.toString(),
172+
item_ids: result.item_ids.map((id) => id.toString()),
173+
amounts: result.amounts.map((amount) => amount.toString()),
174+
currency_amount: result.currency_amount.toString(),
175+
fee_amounts: result.fee_amounts.map((amount) => amount.toString()),
176+
};
177+
});
178+
179+
console.log(rowsToUpsert);
180+
181+
// Upsert rows
182+
console.log("Upserting rows");
183+
const res = await supabase.from("sales").upsert(rowsToUpsert);
184+
console.log(res);
185+
};
186+
187+
main();

0 commit comments

Comments
 (0)