Skip to main content

TypeScript SDK 🔧

The DolphinPay TypeScript SDK (@dolphinpay/sdk) is a type-safe interface for the DolphinPay smart contracts on Sui.

Key facts:

  • USDC only — payments use native Circle USDC with 6 decimals. Amounts crossing the SDK boundary are base units (1 USDC = 1_000_000 units).
  • Zero fees — the protocol admin fee is 0 bps by policy, and there is no merchant fee.
  • No refunds — there is no on-chain refund flow.
  • No batch or split payments — these APIs do not exist.
  • Sui gRPC transport — the SDK uses SuiGrpcClient from @mysten/sui/grpc. There is no JSON-RPC, GraphQL, or WebSocket client.

Installation​

There is no stable npm registry release of @dolphinpay/sdk yet. Build the SDK from source and consume it as a local file dependency:

git clone https://github.com/DolphinsLab/dolphin-pay.git
cd dolphin-pay/sdk
bun install
bun run build

Then reference the built sdk/ directory from your project's package.json — in this repository, frontend/package.json does exactly that:

{
"dependencies": {
"@dolphinpay/sdk": "file:../sdk"
}
}

Adjust the relative path to wherever your project sits relative to sdk/. The @dolphinpay/sdk import specifiers work unchanged with the local package.

Requires Node.js ≥ 18. The only runtime dependency is @mysten/sui.

Quick Start​

import { createClient, usdcToUnits, USDC_TYPES } from '@dolphinpay/sdk';

const client = createClient({
network: 'testnet',
packageId: '<PACKAGE_ID>', // from your deployment (see DEPLOYMENT.md)
adminConfigId: '<ADMIN_CONFIG_ID>', // shared AdminConfig object ID
});

// Build a transaction to create a 10 USDC payment
const txb = client.payment.buildCreatePayment({
merchant: '0xMERCHANT_ADDRESS',
amount: usdcToUnits('10'), // "10000000" (6-decimal base units)
currencyType: USDC_TYPES.testnet, // native Circle USDC
description: 'Payment for Product #123',
expirySeconds: 3600,
});
Deployment IDs

The package is live on Sui testnet; there is no mainnet deployment. Take the current packageId and adminConfigId from DEPLOYMENT.md at the repository root — the single source of truth — and never hard-code IDs from old documents.

Building vs. Querying​

The SDK never holds keys and never signs. Its methods fall into two groups:

  • Transaction builders (build*) — synchronous, return a Transaction from @mysten/sui/transactions. You sign and execute it with your own wallet or keypair.
  • Query methods (get*, is*, query*) — async, read chain state over gRPC and return parsed data.

Payment and Merchant builders have matching dryRun* variants that simulate the transaction via gRPC simulateTransaction. Admin builders currently do not have convenience dry-run wrappers; pass their returned Transaction to client.dryRunTransaction(tx, sender) directly.

Signing and executing​

In a React app, use @mysten/dapp-kit:

import { useSignAndExecuteTransaction } from '@mysten/dapp-kit';

const { mutateAsync: signAndExecute } = useSignAndExecuteTransaction();

const txb = client.payment.buildCreatePayment({ /* ... */ });
const result = await signAndExecute({ transaction: txb });
console.log('Digest:', result.digest);

In a backend or script, sign the returned Transaction with a keypair using the standard @mysten/sui signing flow.

Client Configuration​

interface SDKConfig {
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet';
packageId: string; // deployed DolphinPay package
adminConfigId: string; // shared AdminConfig object (required — the contract
// validates currency and fee policy against it)
grpcUrl?: string; // optional custom gRPC fullnode endpoint
}

The constructor validates its configuration: unsupported runtime network values are rejected, packageId and adminConfigId must be well-formed object IDs (all-zero IDs such as 0x0 are rejected), and valid shorthand IDs are normalized to their full form. Note the 'mainnet' network type being accepted does not imply a DolphinPay mainnet deployment exists.

Default gRPC endpoints are the public fullnodes (https://fullnode.<network>.sui.io:443, localnet http://127.0.0.1:9000). See the Initialization guide.

Modules​

ModuleAccessPurpose
Paymentclient.paymentCreate, execute, cancel, and query payments
Merchantclient.merchantRegister and manage merchants, query merchant data
Adminclient.adminAdminCap-gated governance: platform fee, treasury, allowed currency, merchant overrides
Eventsclient.eventsQuery on-chain events, payment history, merchant statistics

The client also exposes client.suiClient (the underlying SuiGrpcClient), client.createTxBlock(), client.getObjectFields(objectId), and client.dryRunTransaction(tx, sender).

Admin module in brief​

Governance is capability-based (requires the deployer-owned AdminCap):

// Read the shared config (fee, treasury, allowed currency, platform stats)
const config = await client.admin.getAdminConfig();
console.log(config.defaultPlatformFeeBps); // 0 by policy
console.log(config.allowedCurrency); // native Circle USDC type, or null until set

// Builders (admin only): buildSetDefaultPlatformFee, buildSetTreasury,
// buildSetAllowedCurrency, buildForceDeactivateMerchant, buildForceActivateMerchant
// Queries: getAdminCap(address), isAdmin(address)

The contract enforces a 10% fee ceiling (ADMIN_CONSTANTS.MAX_PLATFORM_FEE_BPS = 1000), and any non-zero fee requires a configured treasury plus explicit product approval.

Utility Functions​

import {
usdcToUnits, unitsToUsdc, normalizeAmount,
calculateFee, calculateFeeBreakdown,
validateAddress, validatePaymentAmount, validateDescription,
validateMetadata, validateExpiry,
timestampToDate, isPaymentExpired, getExpiryTimestamp,
} from '@dolphinpay/sdk';

usdcToUnits('12.34'); // "12340000"
unitsToUsdc('12340000'); // "12.34"

// Fee helpers (platform fee is 0 bps by policy — read the live rate
// from AdminConfig via client.admin.getAdminConfig())
calculateFee('10000000', 0); // "0"
calculateFeeBreakdown('10000000', 0);
// { amount: "10000000", platformFee: "0", totalFee: "0", netAmount: "10000000" }

FeeCalculation has no merchant-fee field — merchants have no fee configuration.

Constants​

import {
MODULES, // { PAYMENT, MERCHANT, ADMIN, EVENTS }
PAYMENT_CONSTANTS, // MAX_PAYMENT_AMOUNT "1000000000000" (= 1,000,000 USDC),
// MAX_DESCRIPTION_LENGTH 500, MAX_METADATA_ENTRIES 10,
// MAX_EXPIRY_SECONDS 31536000, DEFAULT_EXPIRY_SECONDS 3600
MERCHANT_CONSTANTS, // MAX_NAME_LENGTH 100, MAX_DESCRIPTION_LENGTH 500
ADMIN_CONSTANTS, // MAX_PLATFORM_FEE_BPS 1000 (10% contract ceiling)
USDC_TYPES, // { mainnet, testnet } — native Circle USDC coin types
USDC_DECIMALS, // 6
ERROR_MESSAGES,
CONVERSIONS, // UNITS_PER_USDC 1_000_000, BPS_DIVISOR 10000
} from '@dolphinpay/sdk';

Dry Run Testing​

Payment and Merchant builders have matching dryRun* methods that simulate via gRPC:

const result = await client.payment.dryRunCreatePayment(params, '0xSENDER_ADDRESS');

if (result.success) {
// result.effects, result.events, result.balanceChanges
const txb = client.payment.buildCreatePayment(params);
await signAndExecute({ transaction: txb });
} else {
console.error('Simulation failed:', result.error ?? result.status);
}

Error Handling​

Builders validate inputs locally and throw before any gas is spent:

try {
client.payment.buildCreatePayment({
merchant: '0xMERCHANT_ADDRESS',
amount: '-100', // invalid
currencyType: USDC_TYPES.testnet,
description: 'Test',
});
} catch (error) {
console.error(error.message); // "Amount must be greater than 0"
}

On-chain aborts map to the exported PaymentErrorCode and MerchantErrorCode enums (e.g. E_AMOUNT_MISMATCH = 104, E_MERCHANT_INACTIVE = 111).

Exported Types​

import type {
SDKConfig,
Payment, PaymentQueryResult, CreatePaymentParams,
CreatePaymentWithMerchantParams, ExecutePaymentParams,
ExecutePaymentWithMerchantParams, CancelPaymentParams,
Merchant, MerchantCap, MerchantQueryResult, RegisterMerchantParams,
AdminConfig, EventQueryParams, EventQueryResult, PaymentHistoryEntry,
FeeCalculation,
} from '@dolphinpay/sdk';

import { PaymentStatus, PaymentErrorCode, MerchantErrorCode } from '@dolphinpay/sdk';

Guides​