API Reference
Coset SDK API reference.
Exports
Coset(class)Networks(enum)PaymentToken(enum)UpdateOptions(type)IRead(interface)IUpdate(interface)
Types
Networks (enum)
export enum Networks {
MANTLE = "mantle",
MANTLE_TESTNET = "mantle-testnet",
}PaymentToken (enum)
export enum PaymentToken {
USDC = "USDC",
CST = "CST",
}UpdateOptions (type)
export type UpdateOptions = {
force?: boolean;
};force: whentrue, bypasses thespent >= spendingLimitguard inCoset.update()/Coset.strictRead()(update path only).
IRead (interface)
export interface IRead {
data: Record<string, any>;
message?: string;
lastUpdateTimestamp?: number;
lastUpdateFormatted?: string;
isUpdateRecommended?: boolean;
recommendedUpdateDuration?: number;
}data: oracle response payload returned from the Coset node.message(optional): error message (see notes underCoset.read()/Coset.strictRead()).lastUpdateTimestamp(optional): UNIX timestamp (seconds) of last on-chain update.lastUpdateFormatted(optional): ISO timestamp derived fromlastUpdateTimestamp.isUpdateRecommended(optional): whether (now - lastUpdateTimestamp >= recommendedUpdateDuration).recommendedUpdateDuration(optional): recommended update interval (seconds).
IUpdate (interface)
export interface IUpdate {
spent: {
total: number;
gasFee: number;
platformFee: number;
dataProviderFee: number;
};
data?: any;
tx?: string;
message?: string;
}spent: cost breakdown (numbers are derived from x402 settlementpriceDetails; seeCoset.update()).data(optional): update response payload (data.datafrom node response).tx(optional): transaction hash (data.transactionHashfrom node response).message(optional): error message (only present on rejected results, not returned values).
Class: Coset
Construction
new Coset(
networkName: Networks,
paymentToken: PaymentToken,
oracleAddress: `0x${string}`,
privateKey: `0x${string}`,
nodeEndpoint?: string
)networkName: selects token address mapping (see “Payment token resolution” below).paymentToken: selects the token symbol which is mapped to an on-chain token address.oracleAddress: used to build the free-call base path; must match/^0x[0-9a-fA-F]+$/.privateKey: used to derive an EVM account signer (internally viaviem); if missing0xor not length66, the implementation prepends0x(no further validation).nodeEndpoint(optional): overrides the default node base URL. Must be a valid URL string accepted bynew URL(nodeEndpoint). If it does not end with/, a trailing slash is added.
Throws
Error("Invalid oracle address")iforacleAddressfails the regex check.Error("Invalid node endpoint")ifnodeEndpointis provided but cannot be parsed bynew URL(nodeEndpoint).
Runtime behavior
- Node base URL (
node):- default:
https://node1.coset.dev/ - overridden by
nodeEndpoint(normalized to end with/)
- default:
- Free-call base URL (
call): always built as:call = "<node>call/<oracleAddress>/"(used byread(),isUpdateNeeded(),getUpdateCost(), and internal balance/metadata calls)
- Paid update endpoint:
POST "<node>update"(used byupdate())
Payment token resolution (internal map)
Networks.MANTLE:PaymentToken.USDC→0x09bc4e0d864854c6afb6eb9a9cdf58ac190d0df9PaymentToken.CST→0x77A90090C9bcc45940E18657fB82Fb70A2D494fd
Networks.MANTLE_TESTNET:PaymentToken.USDC→0x05856b07544044873616d390Cc50c785fe8a8885PaymentToken.CST→0x77A90090C9bcc45940E18657fB82Fb70A2D494fd
Public properties
spent: number
- Default:
0 - Mutations: incremented by
Coset.update()on success (this.spent += spent.total).
spendingLimit: number
- Default:
Infinity - Used by:
Coset.update()(guarded unlessUpdateOptions.force === true).
Public methods
update(options?: UpdateOptions): Promise<IUpdate>
async update(options: UpdateOptions = { force: false }): Promise<IUpdate>Performs a paid update by POSTing to POST <node>update using x402 payment via wrapFetchWithPayment.
Parameters
options.force(default:false): bypasses spending limit check.
Resolves with:
- An
IUpdatecontaining:spent: populated from x402 settlementrequirements.extra.priceDetails(numbers are coerced withNumber(...)).data:data.datafrom the node JSON response.tx:data.transactionHashfrom the node JSON response.
Side effects
- On success: increments
this.spentbyspent.total. - Registers an x402
onBeforePaymentCreationhook each timeupdate()is called (to check token balance).
Rejects with an object (not an Error) in these cases:
- Spending limit exceeded (before any network call), when
this.spent >= this.spendingLimitandoptions.force !== true:
{
message: "Spending limit exceeded",
spent: { total: 0, gasFee: 0, platformFee: 0, dataProviderFee: 0 },
}- Update request failed (
response.ok === falseafter POST):
{
message: `Update failed with status ${status}`,
spent: { total: 0, gasFee: 0, platformFee: 0, dataProviderFee: 0 },
data: any, // node JSON response
}- Payment settlement failed (
paymentResponse.success === false):
{
message: paymentResponse.errorReason,
spent: { total: 0, gasFee: 0, platformFee: 0, dataProviderFee: 0 },
data: any, // node JSON response
}- Other failures (exceptions thrown during processing):
{
message: string, // error.message || "Update failed"
spent: { total: 0, gasFee: 0, platformFee: 0, dataProviderFee: 0 },
}Notes:
- The “insufficient token balance” check aborts payment creation inside x402; the message surfaced to callers depends on the x402 library behavior (the SDK sets
reason: "Insufficient token balance for payment"in the hook).
optionalUpdate(): Promise<null | IUpdate>
async optionalUpdate(): Promise<null | IUpdate>Calls isUpdateNeeded(), and if it returns true, calls update() but does not return its result.
Resolves with:
- Always
null(even if an update was performed).
Rejects
- If
isUpdateNeeded()rejects,optionalUpdate()rejects. - If
update()rejects (when an update is needed),optionalUpdate()rejects with the same rejection value asupdate().
isUpdateNeeded(): Promise<boolean>
async isUpdateNeeded(): Promise<boolean>Fetches update metadata from the node and computes:
Math.floor(Date.now() / 1000) - lastUpdateTimestamp >= recommendedUpdateDuration
Resolves with:
trueif update is needed, elsefalse.
Rejects
- If the metadata fetch fails (node/network/JSON errors), rejects with the underlying rejection object from the internal node call.
read(strict?: boolean): Promise<IRead>
async read(strict = false): Promise<IRead>Fetches oracle data and update metadata concurrently.
Parameters
strict(default:false):false→ calls node pathget-data-without-checktrue→ calls node pathget-data
Resolves with an IRead shaped object containing:
data: result of the node “get data” call (whatever JSON it returns)lastUpdateTimestamp,recommendedUpdateDuration: fromget-update-metadataisUpdateRecommended: computed from metadatalastUpdateFormatted: ISO string fromlastUpdateTimestamp
Error behavior (important)
- This method does not reject on failure; it returns the caught error value as-is:
- on failure, the resolved value may be an object like
{ message: string, data?: any }coming from internal node calls.
- on failure, the resolved value may be an object like
strictRead(options?: UpdateOptions): Promise<IRead>
async strictRead(options: UpdateOptions = { force: false }): Promise<IRead>Implementation behavior:
- First attempts
return await this.read(true). - Only if
read(true)throws (rejects), it performsupdate(options)and returns{ data }from the update result.
Resolves with:
- Usually: the same value returned by
read(true)(seeread()). - Fallback path:
{ data: any }wheredatais fromupdate()’s resolved value.
Notes
- Because
read(true)typically returns errors instead of throwing, the update fallback may be unreachable for many failure modes (depends on whetherread(true)throws vs returns an error object).
getUpdateCost(): Promise<{ units: string; amount: number }>
async getUpdateCost(): Promise<{ units: string; amount: number }>Fetches update price from the node path get-data-update-price.
Resolves with:
{ units: string; amount: number }(shape returned by the node; not validated beyondawait res.json()).
Rejects
- If the underlying node call fails (HTTP error / JSON parse error / network), rejects with the internal rejection object:
{ message: string, data?: any }
setSpendingLimit(spendingLimit: number): Promise<void>
async setSpendingLimit(_spendingLimit: number): Promise<void>Sets this.spendingLimit to _spendingLimit.
Resolves with:
void(immediately).