Skip to main content

TypeScript SDK ๐Ÿ”ง

The DolphinPay TypeScript SDK provides a complete, type-safe interface for interacting with DolphinPay smart contracts on the Sui blockchain.

Featuresโ€‹

  • ๐Ÿ”’ Type Safety: Full TypeScript support with comprehensive type definitions
  • ๐Ÿงฉ Modular Design: Separate modules for Payment and Merchant operations
  • โšก Transaction Building: Build transactions without executing them for full control
  • ๐Ÿงช Dry Run Testing: Test transactions before execution to estimate gas and catch errors
  • ๐Ÿ” Query Support: Query payment and merchant data from the blockchain
  • ๐Ÿ› ๏ธ Utility Functions: Helper functions for amount conversion, fee calculation, and validation
  • ๐ŸŒ Multi-Network: Support for mainnet, testnet, devnet, and localnet
  • โœ… Testnet Ready: Deployed to Sui testnet and ready for integration testing

Installationโ€‹

# npm
npm install @dolphinpay/sdk

# yarn
yarn add @dolphinpay/sdk

# bun
bun add @dolphinpay/sdk

Quick Startโ€‹

1. Initialize Clientโ€‹

import { createClient } from "@dolphinpay/sdk"

// Using testnet deployment
const client = createClient({
packageId:
"0x9c7ca262d020b005e0e6b6a5d083b329d58716e0d80c07b46804324074468f9c",
network: "testnet",
})

2. Create a Paymentโ€‹

import { suiToMist } from "@dolphinpay/sdk"

// Build payment creation transaction
const txb = client.payment.buildCreatePayment({
merchant: "0xmerchant_address_here",
amount: suiToMist(10), // 10 SUI
currency: "SUI",
description: "Payment for premium subscription",
metadata: {
orderId: "ORDER-123",
customerId: "CUST-456",
},
expirySeconds: 3600, // 1 hour
})

// Execute with wallet
const result = await wallet.signAndExecuteTransactionBlock({
transactionBlock: txb,
})

console.log("Payment created:", result.digest)

3. Execute a Paymentโ€‹

// Build payment execution transaction
const txb = client.payment.buildExecutePayment(
{
paymentId: "0xpayment_object_id",
coinObjectId: "0xcoin_object_id",
},
"0x2::sui::SUI"
) // Currency type

// Execute with wallet
const result = await wallet.signAndExecuteTransactionBlock({
transactionBlock: txb,
})

Client Configurationโ€‹

Network Optionsโ€‹

type Network = "mainnet" | "testnet" | "devnet" | "localnet"

const client = createClient({
packageId: "0x...", // Your deployed package ID
network: "testnet", // Network to use
rpcUrl: "https://...", // Optional: custom RPC endpoint
})

Custom RPC Endpointsโ€‹

// Testnet
const testnetClient = createClient({
packageId: "0x...",
network: "testnet",
rpcUrl: "https://fullnode.testnet.sui.io:443",
})

// Mainnet
const mainnetClient = createClient({
packageId: "0x...",
network: "mainnet",
rpcUrl: "https://fullnode.mainnet.sui.io:443",
})

// Local development
const localClient = createClient({
packageId: "0x...",
network: "localnet",
rpcUrl: "http://127.0.0.1:9000",
})

Payment Operationsโ€‹

Create Paymentโ€‹

const txb = client.payment.buildCreatePayment({
merchant: "0xmerchant_address",
amount: suiToMist(100), // Amount in MIST (smallest unit)
currency: "0x2::sui::SUI", // Currency type name
description: "Product purchase", // Description (max 500 chars)
metadata: {
// Additional data (max 10 entries)
orderId: "12345",
customerEmail: "[email protected]",
},
expirySeconds: 3600, // Expiry time (1 hour)
})

Execute Paymentโ€‹

const txb = client.payment.buildExecutePayment(
{
paymentId: "0xpayment_object_id", // Payment object ID
coinObjectId: "0xcoin_object_id", // Coin to use for payment
},
"0x2::sui::SUI"
) // Currency type

Cancel Paymentโ€‹

const txb = client.payment.buildCancelPayment({
paymentId: "0xpayment_object_id", // Payment to cancel
merchantCapId: "0xmerchant_cap_id", // Merchant capability
})

Query Paymentโ€‹

// Get full payment details
const payment = await client.payment.getPayment("0xpayment_id")
console.log("Amount:", payment.payment.amount)
console.log("Status:", payment.payment.status)
console.log("Merchant:", payment.payment.merchant)

// Get payment status only
const status = await client.payment.getPaymentStatus("0xpayment_id")
console.log("Status code:", status)

// Check if payment expired
const expired = await client.payment.isPaymentExpired("0xpayment_id")
console.log("Expired:", expired)

Merchant Operationsโ€‹

Register Merchantโ€‹

const txb = client.merchant.buildRegisterMerchant({
name: "My Online Store",
description: "E-commerce platform for digital goods",
feeConfig: {
customFeeBps: 50, // 0.5% custom fee
minFee: "1000000", // 0.001 SUI minimum
maxFee: "1000000000", // 1 SUI maximum
},
})

Configure Merchant Feesโ€‹

const txb = client.merchant.buildConfigureMerchantFees({
merchantObjectId: "0xmerchant_object_id",
merchantCapId: "0xmerchant_cap_id",
customFeeBps: 100, // 1% custom fee
minFee: "1000000", // 0.001 SUI min
maxFee: "1000000000", // 1 SUI max
})

Add Currency Supportโ€‹

const txb = client.merchant.buildAddSupportedCurrency({
merchantObjectId: "0xmerchant_object_id",
merchantCapId: "0xmerchant_cap_id",
currencyType: "0x2::sui::SUI",
receivingAddress: "0xmerchant_wallet_address",
})

Update Receiving Addressโ€‹

const txb = client.merchant.buildSetReceivingAddress({
merchantObjectId: "0xmerchant_object_id",
merchantCapId: "0xmerchant_cap_id",
currencyType: "0x2::sui::SUI",
address: "0xnew_receiving_address",
})

Utility Functionsโ€‹

Amount Conversionโ€‹

import { suiToMist, mistToSui } from "@dolphinpay/sdk"

// Convert SUI to MIST (1 SUI = 1,000,000,000 MIST)
const mist = suiToMist(10) // "10000000000"
const sui = mistToSui("10000000000") // 10

Fee Calculationโ€‹

import { calculateFee, calculateFeeBreakdown } from "@dolphinpay/sdk"

// Calculate single fee (30 bps = 0.3%)
const fee = calculateFee("10000000000", 30) // "30000000"

// Get full breakdown
const breakdown = calculateFeeBreakdown("10000000000", 50)
console.log(breakdown)
// {
// amount: "10000000000",
// platformFee: "30000000", // 0.3% platform fee
// merchantFee: "50000000", // 0.5% merchant fee
// totalFee: "80000000", // 0.8% total fee
// netAmount: "9920000000" // Amount after fees
// }

Validationโ€‹

import {
validatePaymentAmount,
validateDescription,
validateMetadata,
validateExpiry,
} from "@dolphinpay/sdk"

// Validate payment amount
validatePaymentAmount(suiToMist(100)) // throws if invalid

// Validate description
validateDescription("Payment for order #123") // throws if too long

// Validate metadata
validateMetadata({ orderId: "123", customerId: "456" }) // throws if too many entries

// Validate expiry time
validateExpiry(3600) // throws if invalid range

Dry Run Testingโ€‹

Test transactions before execution to catch errors and estimate gas:

// Test payment creation
const result = await client.payment.dryRunCreatePayment({
merchant: '0xmerchant_address',
amount: suiToMist(100),
currency: '0x2::sui::SUI',
description: 'Test payment',
metadata: {},
expirySeconds: 3600,
}, '0xuser_address'); // Sender address for dry run

if (result.success) {
console.log('โœ… Transaction will succeed!');
console.log('Gas estimate:', result.effects.gasUsed);
console.log('Objects created:', result.objectChanges?.length);

// Now execute the real transaction
const txb = client.payment.buildCreatePayment({...});
await wallet.signAndExecuteTransactionBlock({ transactionBlock: txb });
} else {
console.error('โŒ Transaction would fail:', result.error);
// Fix the error before trying real transaction
}

Error Handlingโ€‹

All SDK methods throw descriptive errors:

try {
const txb = client.payment.buildCreatePayment({
merchant: "0xinvalid_address",
amount: "-100", // Invalid amount
currency: "INVALID",
description: "Test",
})
} catch (error) {
console.error("Validation error:", error.message)
// "Amount must be greater than 0"
// "Invalid merchant address format"
// "Unsupported currency type"
}

Constants and Typesโ€‹

Payment Constantsโ€‹

import { PAYMENT_CONSTANTS } from "@dolphinpay/sdk"

console.log(PAYMENT_CONSTANTS.PLATFORM_FEE_BPS) // 30 (0.3%)
console.log(PAYMENT_CONSTANTS.MAX_PAYMENT_AMOUNT) // "1000000000000" (1000 SUI)
console.log(PAYMENT_CONSTANTS.MAX_DESCRIPTION_LENGTH) // 500
console.log(PAYMENT_CONSTANTS.DEFAULT_EXPIRY_SECONDS) // 3600 (1 hour)

Merchant Constantsโ€‹

import { MERCHANT_CONSTANTS } from "@dolphinpay/sdk"

console.log(MERCHANT_CONSTANTS.MAX_CUSTOM_FEE_BPS) // 1000 (10%)
console.log(MERCHANT_CONSTANTS.MAX_NAME_LENGTH) // 100

Sui Typesโ€‹

import { SUI_TYPES } from "@dolphinpay/sdk"

console.log(SUI_TYPES.SUI) // "0x2::sui::SUI"
console.log(SUI_TYPES.COIN) // "0x2::coin::Coin"

Event Handlingโ€‹

Listen to blockchain events for real-time updates:

import { SuiClient } from "@mysten/sui.js/client"

// Create event listener
const suiClient = new SuiClient({ url: "https://fullnode.testnet.sui.io:443" })

// Listen for payment events
suiClient.subscribeEvent({
filter: {
MoveEventType: `${packageId}::events::PaymentCreated`,
},
onMessage: (event) => {
console.log("New payment created:", event.parsedJson)
},
})

Type Definitionsโ€‹

The SDK exports comprehensive TypeScript types:

import type {
Payment,
PaymentStatus,
CreatePaymentParams,
Merchant,
FeeConfig,
RegisterMerchantParams,
Network,
ClientConfig,
// ... and many more
} from "@dolphinpay/sdk"

Testingโ€‹

Integration Testsโ€‹

# Install dependencies
npm install

# Run integration tests (requires testnet SUI)
npm run test:integration

Test Coverageโ€‹

  • โœ… Client initialization (12 tests)
  • โœ… Payment module operations (12 tests)
  • โœ… Merchant module operations (14 tests)
  • โœ… Utility functions (16 tests)
  • โœ… Error handling (8 tests)
  • โœ… Dry run functionality (6 tests)

Examplesโ€‹

See our comprehensive guides for complete working examples:

Best Practicesโ€‹

1. Always Validate Inputsโ€‹

// โœ… Good: Validate before building transaction
const amount = suiToMist(100)
validatePaymentAmount(amount)

const txb = client.payment.buildCreatePayment({
merchant: validateAddress(merchantAddress),
amount,
currency: "0x2::sui::SUI",
description: "Valid description",
metadata: {},
expirySeconds: 3600,
})

// โŒ Bad: Let SDK throw errors (wastes gas)
try {
const txb = client.payment.buildCreatePayment({
merchant: "invalid-address",
amount: "-100",
// ...
})
} catch (error) {
// Error caught, but user still pays for failed transaction
}

2. Use Dry Run for Testingโ€‹

// โœ… Good: Test first, then execute
const dryResult = await client.payment.dryRunCreatePayment(params, userAddress)
if (!dryResult.success) {
throw new Error(`Transaction would fail: ${dryResult.error}`)
}

const txb = client.payment.buildCreatePayment(params)
await wallet.signAndExecuteTransactionBlock({ transactionBlock: txb })

// โŒ Bad: Execute without testing (risky)
const txb = client.payment.buildCreatePayment(params)
await wallet.signAndExecuteTransactionBlock({ transactionBlock: txb })

3. Handle All Error Typesโ€‹

// โœ… Good: Comprehensive error handling
try {
const result = await wallet.signAndExecuteTransactionBlock({
transactionBlock: txb,
})

if (result.effects?.status?.error) {
throw new Error(`Transaction failed: ${result.effects.status.error}`)
}

console.log("Success:", result.digest)
} catch (error) {
if (error.message?.includes("insufficient")) {
// Handle insufficient balance
showBalanceError()
} else if (error.message?.includes("expired")) {
// Handle expired payment
showExpiryError()
} else {
// Handle other errors
showGenericError(error.message)
}
}

Migration Guideโ€‹

Upgrading from v0.1.0โ€‹

// Before (v0.1.0)
const client = new DolphinPayClient({
packageId: "0x...",
network: "testnet",
})

// After (v0.2.0+)
import { createClient } from "@dolphinpay/sdk"
const client = createClient({
packageId: "0x...",
network: "testnet",
})

Troubleshootingโ€‹

Common Issuesโ€‹

"Amount must be greater than 0"

// โŒ Wrong
client.payment.buildCreatePayment({
amount: 0, // Invalid!
// ...
})

// โœ… Correct
client.payment.buildCreatePayment({
amount: suiToMist(0.1), // 0.1 SUI minimum
// ...
})

"Invalid merchant address format"

// โŒ Wrong
client.payment.buildCreatePayment({
merchant: "merchant_address", // Missing 0x prefix
// ...
})

// โœ… Correct
client.payment.buildCreatePayment({
merchant: "0x1234567890abcdef...", // Valid Sui address
// ...
})

"Transaction would fail" (Dry Run)

// Check dry run result
const dryResult = await client.payment.dryRunCreatePayment(params, userAddress)

if (!dryResult.success) {
console.log("Error:", dryResult.error)
console.log("Gas estimate:", dryResult.effects?.gasUsed)
// Fix issues before real execution
}

Supportโ€‹


Ready to build something amazing? Check out the Basic Payment Example to see DolphinPay in action!