Skip to content

Commit

Permalink
fix basis points rounding (#1344)
Browse files Browse the repository at this point in the history
* fix basis points rounding

* fix

* use bigints

* fix

* improve fn names
  • Loading branch information
ryanio authored Jan 3, 2024
1 parent 27054e7 commit c119561
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 18 deletions.
7 changes: 4 additions & 3 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { ethers } from "ethers";
import { FixedNumber, ZeroAddress } from "ethers";

export const INVERSE_BASIS_POINT = 10_000; // 100 basis points per 1%
export const FIXED_NUMBER_100 = FixedNumber.fromValue(100);
export const INVERSE_BASIS_POINT = 10_000n; // 100 basis points per 1%
export const MAX_EXPIRATION_MONTHS = 1;

export const API_BASE_MAINNET = "https://api.opensea.io";
export const API_BASE_TESTNET = "https://testnets-api.opensea.io";

export const DEFAULT_ZONE = ethers.ZeroAddress;
export const DEFAULT_ZONE = ZeroAddress;
export const ENGLISH_AUCTION_ZONE_MAINNETS =
"0x110b2b128a9ed1be5ef3232d8e4e41640df5c2cd";
export const ENGLISH_AUCTION_ZONE_TESTNETS =
Expand Down
20 changes: 9 additions & 11 deletions src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ import {
hasErrorCode,
getAssetItemType,
getAddressAfterRemappingSharedStorefrontAddressToLazyMintAdapterAddress,
feesToBasisPoints,
requireValidProtocol,
getWETHAddress,
isTestChain,
basisPointsForFee,
totalBasisPointsForFees,
} from "./utils/utils";

/**
Expand Down Expand Up @@ -244,12 +245,9 @@ export class OpenSeaSDK {

private getAmountWithBasisPointsApplied = (
amount: bigint,
basisPoints: number,
basisPoints: bigint,
): string => {
return (
(amount * BigInt(basisPoints)) /
BigInt(INVERSE_BASIS_POINT)
).toString();
return ((amount * basisPoints) / INVERSE_BASIS_POINT).toString();
};

private async getFees({
Expand All @@ -266,10 +264,10 @@ export class OpenSeaSDK {
endAmount?: bigint;
}): Promise<ConsiderationInputItem[]> {
const collectionFees = collection.fees;
const collectionFeesBasisPoints = feesToBasisPoints(collectionFees);
const collectionFeesBasisPoints = totalBasisPointsForFees(collectionFees);
const sellerBasisPoints = INVERSE_BASIS_POINT - collectionFeesBasisPoints;

const getConsiderationItem = (basisPoints: number, recipient?: string) => {
const getConsiderationItem = (basisPoints: bigint, recipient?: string) => {
return {
token: paymentTokenAddress,
amount: this.getAmountWithBasisPointsApplied(startAmount, basisPoints),
Expand All @@ -288,7 +286,7 @@ export class OpenSeaSDK {
}
for (const fee of collectionFees) {
considerationItems.push(
getConsiderationItem(fee.fee * 100, fee.recipient),
getConsiderationItem(basisPointsForFee(fee), fee.recipient),
);
}
return considerationItems;
Expand Down Expand Up @@ -1106,10 +1104,10 @@ export class OpenSeaSDK {

// Validation
if (startAmount == null || startAmountWei < 0) {
throw new Error(`Starting price must be a number >= 0`);
throw new Error("Starting price must be a number >= 0");
}
if (isEther && orderSide === OrderSide.BID) {
throw new Error(`Offers must use wrapped ETH or an ERC-20 token.`);
throw new Error("Offers must use wrapped ETH or an ERC-20 token.");
}
if (priceDiffWei < 0) {
throw new Error(
Expand Down
27 changes: 23 additions & 4 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import {
CROSS_CHAIN_SEAPORT_V1_5_ADDRESS,
ItemType,
} from "@opensea/seaport-js/lib/constants";
import { ethers } from "ethers";
import { ethers, FixedNumber } from "ethers";
import {
MAX_EXPIRATION_MONTHS,
SHARED_STOREFRONT_LAZY_MINT_ADAPTER_CROSS_CHAIN_ADDRESS,
SHARED_STOREFRONT_ADDRESSES,
FIXED_NUMBER_100,
} from "../constants";
import {
Chain,
Expand Down Expand Up @@ -224,9 +225,27 @@ export const getAddressAfterRemappingSharedStorefrontAddressToLazyMintAdapterAdd
* @param fees The fees to sum up
* @returns sum of basis points
*/
export const feesToBasisPoints = (fees: Fee[]): number => {
const feeBasisPoints = fees.map((fee) => fee.fee * 100);
return feeBasisPoints.reduce((sum, basisPoints) => basisPoints + sum, 0);
export const totalBasisPointsForFees = (fees: Fee[]): bigint => {
const feeBasisPoints = fees.map((fee) => basisPointsForFee(fee));
const totalBasisPoints = feeBasisPoints.reduce(
(sum, basisPoints) => basisPoints + sum,
0n,
);
return totalBasisPoints;
};

/**
* Converts a fee to its basis points representation.
* @param fee The fee to convert
* @returns the basis points
*/
export const basisPointsForFee = (fee: Fee): bigint => {
return BigInt(
FixedNumber.fromString(fee.fee.toString())
.mul(FIXED_NUMBER_100)
.toFormat(0) // format to 0 decimal places to convert to bigint
.toString(),
);
};

/**
Expand Down

0 comments on commit c119561

Please sign in to comment.