From 7d3c62695d49cd03d672c640661e2a9991c1a644 Mon Sep 17 00:00:00 2001 From: Osraka <98612432+Osraka@users.noreply.github.com> Date: Tue, 22 Sep 2026 00:32:13 +0300 Subject: [PATCH] fix(sdk): use six decimals for new chain offer tokens --- src/sdk.ts | 4 +- src/utils/chain.ts | 11 ++++++ src/viem.ts | 4 +- test/sdk/getPriceParameters.spec.ts | 61 ++++++++++++++++++++++++++++- test/utils/chain.spec.ts | 13 ++++++ 5 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/sdk.ts b/src/sdk.ts index 756a1f03f..2dd3528d7 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -12,6 +12,7 @@ import { getDefaultConduit, getListingPaymentToken, getOfferPaymentToken, + getOfferPaymentTokenDecimals, getSeaportAddress, } from "./utils/utils" @@ -62,7 +63,8 @@ export class OpenSeaSDK extends BaseOpenSeaSDK { }) const cachedPaymentTokenDecimals: { [address: string]: number } = {} - cachedPaymentTokenDecimals[getOfferPaymentToken(chain).toLowerCase()] = 18 + cachedPaymentTokenDecimals[getOfferPaymentToken(chain).toLowerCase()] = + getOfferPaymentTokenDecimals(chain) cachedPaymentTokenDecimals[getListingPaymentToken(chain).toLowerCase()] = 18 super({ diff --git a/src/utils/chain.ts b/src/utils/chain.ts index 1fbfc93cb..aaa1db72e 100644 --- a/src/utils/chain.ts +++ b/src/utils/chain.ts @@ -118,6 +118,17 @@ export const getOfferPaymentToken = (chain: Chain) => { } } +/** Returns the decimals for the chain's default offer currency. */ +export const getOfferPaymentTokenDecimals = (chain: Chain): number => { + switch (chain) { + case Chain.Arc: + case Chain.StableChain: + return 6 + default: + return 18 + } +} + /** * Returns the default currency for listings on the given chain. * @param chain The chain to get the listing payment token for diff --git a/src/viem.ts b/src/viem.ts index 149666737..5781c8fab 100644 --- a/src/viem.ts +++ b/src/viem.ts @@ -34,6 +34,7 @@ import { getDefaultConduit, getListingPaymentToken, getOfferPaymentToken, + getOfferPaymentTokenDecimals, getSeaportAddress, } from "./utils/utils" @@ -101,7 +102,8 @@ export class OpenSeaSDK extends BaseOpenSeaSDK { }) const cachedPaymentTokenDecimals: { [address: string]: number } = {} - cachedPaymentTokenDecimals[getOfferPaymentToken(chain).toLowerCase()] = 18 + cachedPaymentTokenDecimals[getOfferPaymentToken(chain).toLowerCase()] = + getOfferPaymentTokenDecimals(chain) cachedPaymentTokenDecimals[getListingPaymentToken(chain).toLowerCase()] = 18 super({ diff --git a/test/sdk/getPriceParameters.spec.ts b/test/sdk/getPriceParameters.spec.ts index ff6f500ad..3518fb56d 100644 --- a/test/sdk/getPriceParameters.spec.ts +++ b/test/sdk/getPriceParameters.spec.ts @@ -1,6 +1,11 @@ +import { ethers } from "ethers" +import { createPublicClient, defineChain, http } from "viem" import { describe, expect, test, vi } from "vitest" +import { OpenSeaSDK } from "../../src" import { ZERO_ADDRESS } from "../../src/constants" -import { OrderSide } from "../../src/types" +import { Chain, OrderSide } from "../../src/types" +import { getChainId, getOfferPaymentToken } from "../../src/utils" +import { OpenSeaSDK as ViemSDK } from "../../src/viem" import { sdk } from "../utils/sdk" describe("SDK: _getPriceParameters", () => { @@ -27,4 +32,58 @@ describe("SDK: _getPriceParameters", () => { ), ).rejects.toThrow("Too many decimal places") }) + + describe.each([ + ["Arc", Chain.Arc], + ["Stable Chain", Chain.StableChain], + ])("%s default offer currency", (_name, chain) => { + const chainId = Number(getChainId(chain)) + const rpcUrl = "http://127.0.0.1:1" + + test.each([ + [ + "ethers", + () => + new OpenSeaSDK( + new ethers.JsonRpcProvider(rpcUrl, chainId, { + staticNetwork: true, + }), + { chain }, + ), + ], + [ + "viem", + () => { + const viemChain = defineChain({ + id: chainId, + name: chain, + nativeCurrency: { name: "Native", symbol: "NATIVE", decimals: 18 }, + rpcUrls: { default: { http: [rpcUrl] } }, + }) + return new ViemSDK( + { + publicClient: createPublicClient({ + chain: viemChain, + transport: http(rpcUrl), + }), + rpcUrl, + }, + { chain }, + ) + }, + ], + ])("uses six decimals with the %s entrypoint", async (_entrypoint, createSDK) => { + const chainSDK = createSDK() + const getPaymentToken = vi.spyOn(chainSDK.api, "getPaymentToken") + + await expect( + (chainSDK as any)._getPriceParameters( + OrderSide.OFFER, + getOfferPaymentToken(chain), + "1.5", + ), + ).resolves.toEqual({ basePrice: 1500000n }) + expect(getPaymentToken).not.toHaveBeenCalled() + }) + }) }) diff --git a/test/utils/chain.spec.ts b/test/utils/chain.spec.ts index 328534b51..498cce2cb 100644 --- a/test/utils/chain.spec.ts +++ b/test/utils/chain.spec.ts @@ -25,6 +25,7 @@ import { getListingPaymentToken, getNativeWrapTokenAddress, getOfferPaymentToken, + getOfferPaymentTokenDecimals, getSeaportAddress, getSignedZone, usesAlternateProtocol, @@ -269,6 +270,18 @@ describe("Utils: chain", () => { }) }) + describe("getOfferPaymentTokenDecimals", () => { + test("returns six for the Arc and Stable Chain offer mirrors", () => { + expect(getOfferPaymentTokenDecimals(Chain.Arc)).toBe(6) + expect(getOfferPaymentTokenDecimals(Chain.StableChain)).toBe(6) + }) + + test("returns 18 for existing wrapped-native offer currencies", () => { + expect(getOfferPaymentTokenDecimals(Chain.Mainnet)).toBe(18) + expect(getOfferPaymentTokenDecimals(Chain.Base)).toBe(18) + }) + }) + describe("getListingPaymentToken", () => { test("returns ETH (0x0) for Mainnet", () => { expect(getListingPaymentToken(Chain.Mainnet)).toBe(ZERO_ADDRESS)