Skip to content

Commit

Permalink
Merge pull request #10 from Offsetra/fix-filter
Browse files Browse the repository at this point in the history
v2.1.0 - Update emissions factor & fix double-counting of certain contract emissions.
  • Loading branch information
brendanmc6 authored Jun 24, 2021
2 parents 6798805 + aae99c9 commit 26f9579
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 13 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ethereum-emissions-calculator",
"version": "2.0.0",
"version": "2.1.0",
"description": "TypeScript utils to calculate the CO2 emissions of an Ethereum wallet. Powered by the Etherscan.io API.",
"main": "./lib/index.js",
"directories": {
Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ export type { CalculatorOptions, AddressEmissionsResult };

/**
* Based on 2021 methodology, see github and carbon.fyi for details.
* Last updated: Mar. 7, 2021
* Last updated: June 24, 2021
*/
const KG_CO2_PER_GAS = 0.0002873993139;
const KG_CO2_PER_GAS = 0.0001809589427;

/**
* Calculate emissions of an address. Emissions are allocated for SENT (outgoing) transactions only.
Expand Down
3 changes: 3 additions & 0 deletions src/test-fixtures/getRandomHash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const getRandomHash = () => {
return `0x${Math.random()}`;
};
33 changes: 33 additions & 0 deletions src/utils/filterValidOutgoingTransactions.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TransactionData } from "../types";
import { filterValidOutgoingTransactions } from "./filterValidOutgoingTransactions";
import { getRandomHash } from "../test-fixtures/getRandomHash";

const SENDER = "0x5abfec25f74cd88437631a7731906932776356f9";
const RECIEVER = "0x3fb1cd2cd96c6d5c0b5eb3322d807b34482481d4";
Expand All @@ -14,10 +15,12 @@ describe("filterValidOutgoingTransactions", () => {
to: RECIEVER,
from: SENDER,
isError: "1",
hash: getRandomHash(),
},
{
to: RECIEVER,
from: SENDER,
hash: getRandomHash(),
},
] as TransactionData[];
expect(filterValidOutgoingTransactions(txns, SENDER)).toHaveLength(1);
Expand All @@ -28,10 +31,12 @@ describe("filterValidOutgoingTransactions", () => {
to: RECIEVER,
from: SENDER,
isError: "0",
hash: getRandomHash(),
},
{
to: RECIEVER,
from: SENDER,
hash: getRandomHash(),
},
] as TransactionData[];
expect(filterValidOutgoingTransactions(txns, SENDER)).toHaveLength(2);
Expand All @@ -41,13 +46,41 @@ describe("filterValidOutgoingTransactions", () => {
{
to: SENDER,
from: RECIEVER,
hash: getRandomHash(),
},
{
to: RECIEVER,
from: SENDER,
hash: getRandomHash(),
},
] as TransactionData[];
expect(filterValidOutgoingTransactions(txns, SENDER)).toHaveLength(1);
expect(true).toBe(true);
});
test("Remove duplicates", () => {
const txns = [
{
to: RECIEVER,
from: SENDER,
isError: "0",
hash: "unique-hash",
},
{
to: RECIEVER,
from: SENDER,
hash: "duplicate-hash",
},
{
to: RECIEVER,
from: SENDER,
hash: "duplicate-hash",
},
{
to: RECIEVER,
from: SENDER,
hash: "duplicate-hash",
},
] as TransactionData[];
expect(filterValidOutgoingTransactions(txns, SENDER)).toHaveLength(2);
});
});
16 changes: 11 additions & 5 deletions src/utils/filterValidOutgoingTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ export const filterValidOutgoingTransactions = (
transactions: TransactionData[],
address: string
): TransactionData[] => {
return transactions.filter((txn: TransactionData) => {
const isOutgoing = txn.from.toLowerCase() === address.toLowerCase();
const succeeded = txn.isError !== "1";
return isOutgoing && succeeded;
});
return transactions.reduce<TransactionData[]>((prev, txn) => {
// since response is sorted, we only need to compare hash of preceeding valid txn
if (
txn.from.toLowerCase() === address.toLowerCase() &&
txn.isError !== "1" &&
prev[prev.length - 1]?.hash !== txn.hash
) {
return prev.concat([txn]);
}
return prev;
}, []);
};
31 changes: 31 additions & 0 deletions src/utils/filterValidTransactions.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TransactionData } from "../types";
import { filterValidTransactions } from "./filterValidTransactions";
import { getRandomHash } from "../test-fixtures/getRandomHash";

const SENDER = "0x5abfec25f74cd88437631a7731906932776356f9";
const RECIEVER = "0x3fb1cd2cd96c6d5c0b5eb3322d807b34482481d4";
Expand All @@ -14,10 +15,12 @@ describe("filterValidTransactions", () => {
to: RECIEVER,
from: SENDER,
isError: "1",
hash: getRandomHash(),
},
{
to: RECIEVER,
from: SENDER,
hash: getRandomHash(),
},
] as TransactionData[];
expect(filterValidTransactions(txns)).toHaveLength(1);
Expand All @@ -28,10 +31,38 @@ describe("filterValidTransactions", () => {
to: RECIEVER,
from: SENDER,
isError: "0",
hash: getRandomHash(),
},
{
to: RECIEVER,
from: SENDER,
hash: getRandomHash(),
},
] as TransactionData[];
expect(filterValidTransactions(txns)).toHaveLength(2);
});
test("Remove duplicates", () => {
const txns = [
{
to: RECIEVER,
from: SENDER,
isError: "0",
hash: "unique-hash",
},
{
to: RECIEVER,
from: SENDER,
hash: "duplicate-hash",
},
{
to: RECIEVER,
from: SENDER,
hash: "duplicate-hash",
},
{
to: RECIEVER,
from: SENDER,
hash: "duplicate-hash",
},
] as TransactionData[];
expect(filterValidTransactions(txns)).toHaveLength(2);
Expand Down
11 changes: 7 additions & 4 deletions src/utils/filterValidTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import { TransactionData } from "../types";
export const filterValidTransactions = (
transactions: TransactionData[]
): TransactionData[] => {
return transactions.filter((txn: TransactionData) => {
const succeeded = txn.isError !== "1";
return succeeded;
});
return transactions.reduce<TransactionData[]>((prev, txn) => {
// since response is sorted, we only need to compare hash of preceeding valid txn
if (txn.isError !== "1" && prev[prev.length - 1]?.hash !== txn.hash) {
return prev.concat([txn]);
}
return prev;
}, []);
};
1 change: 1 addition & 0 deletions src/utils/getAddressTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const getAddressTransactions = async (
return {
done: false, // we can't rely on the txn count for completeness (it might be slightly less than 10k after filtering)
transactions: transactions.filter(
// filter out the lowest block number because we don't know if we captured all of that blocks txns.
(txn) => txn.blockNumber > lowestBlockNumber
),
};
Expand Down

0 comments on commit 26f9579

Please sign in to comment.