Skip to main content

Utilities and constants

Besides createRemesso, the SDK exports the helpers it uses itself. They are pure functions with no network access, unless noted.

Tokens and amounts​

Amounts go in as decimal strings and come out as base units (bigint). Never pass a JavaScript number in between: that is how precision is lost.

import { findToken, formatAmount, token, toUnits } from "remesso-sdk";

const usdt = token("USDT"); // throws for a token Remesso doesn't know
const units = toUnits("2.50", usdt); // 2_500_000n: USDT has 6 decimals
console.log(formatAmount(997_500n, usdt)); // "0.9975 USDT"
console.log(findToken("USAT")?.symbol); // "USA₮": undefined if unknown, never throws
ExportSignatureDescription
token(symbolOrAddress: string) => TokenA token by symbol or address. Throws invalid for one Remesso doesn't know.
findToken(symbolOrAddress: string) => Token | undefinedThe same, returning undefined instead of throwing.
toUnits(amount: string, t: Token) => bigintA decimal string in base units. Throws invalid for a malformed amount or more decimals than the token has.
formatAmount(units: bigint | string, token: Token | string) => stringBase units as a decimal with the symbol, such as "1500 wARS".

Symbols match in any case, and common spellings resolve: USAT and USD₮ to USA₮ and USDT, cUSD to USDm. A Token has symbol, address, decimals, currency, directAllowed, feeCurrency, minPerRun and maxPerRun. The full table is on tokens and limits.

Fees and limits​

The commission is taken from each scheduled payment and rounded up, exactly as the contract rounds it.

import { FEE_BPS, feeOf, grossFor, netOf, runLimits, token, toUnits } from "remesso-sdk";

const usdt = token("USDT");
const gross = toUnits("1", usdt);

feeOf(gross, FEE_BPS); // 2_500n: 0.0025 USDT
netOf(gross, FEE_BPS); // 997_500n: what arrives
grossFor(toUnits("50", usdt), FEE_BPS); // 50_125_314n: send this for exactly 50 to arrive
runLimits(token("wARS")); // { min: 1,500 wARS, max: 1,500,000 wARS }, in base units
ExportSignatureDescription
FEE_BPSnumberRemesso's commission on new schedules, in basis points: 25, or 0.25%.
feeOf(gross: bigint, bps: number) => bigintThe commission on a gross amount, rounded up.
netOf(gross: bigint, bps: number) => bigintWhat the recipient receives from a gross amount.
grossFor(net: bigint, bps: number) => bigintThe smallest gross amount that delivers at least net.
runLimits(t: Token) => { min: bigint; max: bigint }The gross per-payment bounds the executor sends. Throws refused for a token not taken for new schedules.

Memos​

import { memo32 } from "remesso-sdk";

memo32("invoice-42"); // 0x696e766f6963652d3432 followed by zeros: 32 bytes

memo32(memo?) encodes a memo as the bytes32 an agent payment records on-chain, padded on the right. It throws invalid over 32 bytes rather than cutting it. A plain letter is one byte, an accented letter two and an emoji four.

import { parsePayLink, payLink } from "remesso-sdk";

const link = payLink({
to: process.env.RECIPIENT!,
amount: "50",
token: "USDT",
every: "month",
runs: 12,
from: "Ada's studio",
});
// https://remesso.xyz/schedules/new?to=0x…&from=Ada%27s+studio&amount=50&token=USDT&every=month&runs=12

parsePayLink(link); // { to, from, amount: "50", token: "USDT", intervalSeconds: 2592000, runs: 12 }
ExportSignatureDescription
payLink(input: PayLinkInput, origin?: string) => stringA link that opens the Remesso payment form filled in. The amount is what the recipient should receive.
parsePayLink(urlOrQuery: string) => PayLinkWhat a link says, keeping only what validates: a real address, a positive amount, a token taken for new schedules, a cadence the form offers, a request id.

The client's own payLink method defaults to to the client's address.

Webhook verification​

ExportSignatureDescription
webhookHandler(options: WebhookHandlerOptions) => (req: Request) => Promise<Response>A fetch-style handler: answers the subscription challenge for your address, verifies every delivery and calls onPayment once per message.
verifyWebhook(raw, headers, secrets) => Promise<boolean>Whether a raw body was signed with one of your secrets in the last five minutes.
parseWebhook(raw, headers, secrets) => Promise<WebhookMessage>A verified delivery, parsed. Throws for a bad signature or a body that isn't a Remesso payment message.

See webhooks for running them, and webhook payloads for the message format.

Payment stores​

Agent payments are recorded before they are broadcast, so a retry with the same idempotency key can find the first attempt.

ExportDescription
memoryStore()The default: records in memory, lost when the process exits.
fileStore(path?)From remesso-sdk/node. Records in a JSON file with 0600 permissions, by default ~/.remesso-sdk/payments.json. Use one process per file.
PaymentStoreThe interface, to keep records in your own database: byKey(key, deployment), since(ms) and save(record).

Node helpers​

From remesso-sdk/node:

ExportDescription
fileStore(path?)Agent payment records on disk, above.
toNodeListener(handler)Runs a fetch-style handler, such as webhookHandler's, under http.createServer or Express. Mount it before any JSON body parser: the signature covers the raw body.
safeFetchText(url)Fetches an agent's registration file only from public addresses, connecting to the address it checked. Pass it as the client's fetchText.

Deployment constants​

Generated from what is live, never typed by hand.

ExportDescription
deploymentCelo mainnet as Remesso runs it: chain, contracts, tokens and endpoints.
CHAIN_ID42220.
EXECUTORThe RemessoExecutorV5 contract, which holds schedules.
ALLOWANCEThe RemessoAgentAllowance contract, which holds agent policies.
REGISTRYThe ERC-8004 identity registry.
CURRENT_EXECUTOR0x…0001: the trigger value that means Remesso's executor, whichever key it is at the time.
CADENCESweek, fortnight, month (30 days) and quarter (90 days), in seconds.

The addresses are on contracts and endpoints.

ABIs​

executorAbi, allowanceAbi, erc20Abi and registryAbi, for reading or writing the contracts with viem directly.

import { EXECUTOR, executorAbi } from "remesso-sdk";

const [due, funded, approved] = await reader.publicClient.readContract({
address: EXECUTOR,
abi: executorAbi,
functionName: "runnability",
args: [scheduleId],
});
console.log({ due, funded, approved });

Attribution​

ExportDescription
ATTRIBUTIONThe ERC-8021 suffix the SDK appends to every transaction: Remesso's own codes.
attributionFor(builderCodes?, ours?)That suffix with your builder codes after Remesso's, checked by the rules the executor applies. For a transaction you send yourself.

See builder codes.

Errors​

RemessoError is the class of every refusal, with a code (RemessoErrorCode) and sometimes details. See errors.

Types​

Cadence, CreateScheduleInput, CreatedSchedule, Schedule, PayInput, PaymentResult, Policy, CreatePolicyInput, CreateRequestInput, RequestState, RequestStatus, RequestSummary, EventKind, EventQuery, PaymentEvent, WebhookHandlerOptions, WebhookMessage, WebhookType, FoundAgent, PayeeProfile, PayLink, PayLinkInput, PaymentRecord, PaymentStore, Token, Remesso, RemessoOptions and RemessoErrorCode.