Payment Kit SDK
This package is in active development and should be used with caution. APIs are experimental and subject to breaking changes without notice. We recommend thoroughly testing any implementation before using in production environments.
Complete API reference for the Payment Kit SDK.
Client Setup
PaymentKitClient
The main client class that provides access to Payment Kit functionality.
paymentKit()
Function to create a Payment Kit client extension for SuiClient.
paymentKit<Name extends string = 'paymentKit'>({
name = 'paymentKit' as Name,
}): SuiClientRegistration<PaymentKitCompatibleClient, Name, PaymentKitClient>Example:
import { getFullnodeUrl, SuiClient } from '@mysten/sui/client';
import { paymentKit } from '@mysten/payment-kit';
const client = new SuiClient({
url: getFullnodeUrl('testnet'),
network: 'testnet',
}).$extend(paymentKit());
// Access Payment Kit functionality
client.paymentKit.tx.processRegistryPayment(/* ... */);Supported Networks:
testnetmainnet
Throws:
PaymentKitClientErrorif network is unsupported
Transaction Methods
Transaction methods create complete, ready-to-sign transactions.
client.paymentKit.tx.processRegistryPayment()
Create a transaction to process a registry-based payment.
processRegistryPayment(
options: ProcessRegistryPaymentOptions
): TransactionParameters:
type ProcessRegistryPaymentOptions = {
nonce: string; // Unique payment identifier
coinType: string; // Coin type (e.g., '0x2::sui::SUI')
amount: number | bigint; // Amount in smallest unit
receiver: string; // Recipient address
sender: string; // Sender address (must match signer)
} & ({ registryName: string; registryId?: never } | { registryId: string; registryName?: never });Returns: Transaction - Ready-to-sign transaction
Note: If you rather provide the registryId you can do so instead of the registryName.
Example:
const tx = client.paymentKit.tx.processRegistryPayment({
nonce: crypto.randomUUID(),
coinType: '0x2::sui::SUI',
amount: 1000000000,
receiver,
sender: senderAddress,
});
const result = await client.signAndExecuteTransaction({
transaction: tx,
signer: keypair,
});On-Chain Effects:
- Transfers coins from sender to receiver
- Creates a
PaymentRecorddynamic field on the registry - Emits a
PaymentReceiptevent
Throws:
- Error if payment with same key already exists
- Error if sender has insufficient balance
client.paymentKit.tx.processEphemeralPayment()
Create a transaction to process an ephemeral payment (no registry storage).
processEphemeralPayment(
options: ProcessEphemeralPaymentOptions
): TransactionParameters:
type ProcessEphemeralPaymentOptions = {
nonce: string; // Payment identifier (not enforced for uniqueness)
coinType: string; // Coin type
amount: number | bigint; // Amount in smallest unit
receiver: string; // Recipient address
sender: string; // Sender address (must match signer)
};Returns: Transaction - Ready-to-sign transaction
Example:
const tx = client.paymentKit.tx.processEphemeralPayment({
nonce: crypto.randomUUID(),
coinType: '0x2::sui::SUI',
amount: 500000000,
receiver,
sender: senderAddress,
});
const result = await client.signAndExecuteTransaction({
transaction: tx,
signer: keypair,
});On-Chain Effects:
- Transfers coins from sender to receiver
- Emits a
PaymentReceiptevent - No
PaymentRecordcreated (no duplicate prevention)
client.paymentKit.tx.createRegistry()
Create a transaction to create a new payment registry.
createRegistry(options: CreateRegistryOptions): TransactionParameters:
type CreateRegistryOptions = {
registryName: string; // Unique name for the registry
};Returns: Transaction - Ready-to-sign transaction
Example:
const tx = client.paymentKit.tx.createRegistry({
registryName: 'my-payment-registry',
});
const result = await client.signAndExecuteTransaction({
transaction: tx,
signer: keypair,
options: {
showObjectChanges: true,
},
});
// Extract the RegistryAdminCap from result.objectChanges
const adminCap = result.objectChanges?.find(
(change) => change.type === 'created' && change.objectType.includes('RegistryAdminCap'),
);On-Chain Effects:
- Creates a
PaymentRegistryobject - Creates a
RegistryAdminCapowned by sender - Registry ID is deterministically derived from name
Important:
- Registry names must be unique globally
- Save the
RegistryAdminCapobject ID for configuration operations
client.paymentKit.tx.setConfigEpochExpirationDuration()
Create a transaction to set the epoch expiration duration for payment records.
setConfigEpochExpirationDuration(
options: SetEpochExpirationDurationOptions
): TransactionParameters:
type SetEpochExpirationDurationOptions = {
epochExpirationDuration: number | bigint; // Number of epochs before records expire
adminCapId: string; // Admin capability object ID
} & ({ registryName: string; registryId?: never } | { registryId: string; registryName?: never });Returns: Transaction - Ready-to-sign transaction
Example:
const tx = client.paymentKit.tx.setConfigEpochExpirationDuration({
registryName: 'my-registry',
epochExpirationDuration: 60,
adminCapId: adminCapId,
});
await client.signAndExecuteTransaction({
transaction: tx,
signer: keypair,
});Requires:
- Transaction signer must own the admin capability
Default: 30 epochs
client.paymentKit.tx.setConfigRegistryManagedFunds()
Create a transaction to enable/disable registry-managed funds.
setConfigRegistryManagedFunds(
options: SetRegistryManagedFundsOptions
): TransactionParameters:
type SetRegistryManagedFundsOptions = {
registryManagedFunds: boolean; // Enable (true) or disable (false)
adminCapId: string; // Admin capability object ID
} & ({ registryName: string; registryId?: never } | { registryId: string; registryName?: never });Returns: Transaction - Ready-to-sign transaction
Example:
const tx = client.paymentKit.tx.setConfigRegistryManagedFunds({
registryName: 'my-registry',
registryManagedFunds: true,
adminCapId: adminCapId,
});
await client.signAndExecuteTransaction({
transaction: tx,
signer: keypair,
});When Enabled:
- Payment receiver must be the registry itself
- Funds accumulate in the registry
- Admin can withdraw funds later
Default: Disabled (funds go directly to receivers)
client.paymentKit.tx.withdrawFromRegistry()
Create a transaction to withdraw accumulated funds from a registry.
withdrawFromRegistry(
options: WithdrawFromRegistryOptions
): TransactionParameters:
type WithdrawFromRegistryOptions = {
coinType: string; // Coin type to withdraw
adminCapId: string; // Admin capability object ID
} & ({ registryName: string; registryId?: never } | { registryId: string; registryName?: never });Returns: Transaction - Ready-to-sign transaction
Example:
const tx = client.paymentKit.tx.withdrawFromRegistry({
coinType: '0x2::sui::SUI',
registryName: 'my-registry',
adminCapId: adminCapId,
});
const result = await client.signAndExecuteTransaction({
transaction: tx,
signer: keypair,
});Requires:
- Registry must have
registryManagedFundsenabled - Transaction signer must own the admin capability
Effect:
- Withdraws all coins of specified type to the sender
client.paymentKit.tx.deletePaymentRecord()
Create a transaction to delete an expired payment record.
deletePaymentRecord(
options: DeletePaymentRecordOptions
): TransactionParameters:
type DeletePaymentRecordOptions = {
nonce: string; // Payment nonce
coinType: string; // Coin type of the payment
amount: number | bigint; // Payment amount
receiver: string; // Payment receiver
} & ({ registryName: string; registryId?: never } | { registryId: string; registryName?: never });Returns: Transaction - Ready-to-sign transaction
Example:
const tx = client.paymentKit.tx.deletePaymentRecord({
nonce: crypto.randomUUID(),
coinType: '0x2::sui::SUI',
amount: 1000000000,
receiver,
registryName: 'my-registry',
});
const result = await client.signAndExecuteTransaction({
transaction: tx,
signer: keypair,
});Requires:
- Payment record must be expired (current epoch >= record epoch + expiration duration)
- Anyone can delete expired records (permissionless)
Effect:
- Removes the payment record from the registry
- Sender receives storage rebate
Query Methods
client.paymentKit.getPaymentRecord()
Query the blockchain for a payment record.
async getPaymentRecord(
options: GetPaymentRecordOptions
): Promise<GetPaymentRecordResponse | null>Parameters:
type GetPaymentRecordOptions = {
nonce: string; // Payment nonce
coinType: string; // Coin type
amount: number | bigint; // Payment amount
receiver: string; // Payment receiver
} & ({ registryName: string; registryId?: never } | { registryId: string; registryName?: never });Returns:
type GetPaymentRecordResponse = {
key: string; // Dynamic field object ID
paymentTransactionDigest: string | null; // Transaction that created the record
epochAtTimeOfRecord: string; // Epoch when record was created
} | null; // null if record doesn't existExample:
const record = await client.paymentKit.getPaymentRecord({
nonce: crypto.randomUUID(),
coinType: '0x2::sui::SUI',
amount: 1000000000,
receiver,
});
if (record) {
console.log('Payment exists!');
console.log('Transaction:', record.paymentTransactionDigest);
console.log('Created at epoch:', record.epochAtTimeOfRecord);
} else {
console.log('Payment not found');
}Use Cases:
- Verify a payment was completed
- Check for duplicate payments before processing
- Retrieve payment details for reconciliation
Call Methods
Call methods return transaction commands that can be composed in custom transactions. Use these when you need fine-grained control over transaction construction.
client.paymentKit.calls.processRegistryPayment()
Returns a transaction command for registry-based payment.
processRegistryPayment(
options: ProcessRegistryPaymentOptions
): TransactionObjectArgumentExample:
import { Transaction } from '@mysten/sui/transactions';
const tx = new Transaction();
// Add custom logic before payment
tx.moveCall({
target: '0xMyPackage::my_module::pre_payment_check',
arguments: [
/* ... */
],
});
// Add payment command
tx.add(
client.paymentKit.calls.processRegistryPayment({
nonce: crypto.randomUUID(),
coinType: '0x2::sui::SUI',
amount: 1000000000,
receiver,
sender: senderAddress,
}),
);
// Add custom logic after payment
tx.moveCall({
target: '0xMyPackage::my_module::post_payment_action',
arguments: [
/* ... */
],
});
await client.signAndExecuteTransaction({
transaction: tx,
signer: keypair,
});Other Call Methods
All transaction methods have corresponding call methods:
client.paymentKit.calls.processEphemeralPayment()client.paymentKit.calls.createRegistry()client.paymentKit.calls.setConfigEpochExpirationDuration()client.paymentKit.calls.setConfigRegistryManagedFunds()client.paymentKit.calls.withdrawFromRegistry()client.paymentKit.calls.deletePaymentRecord()
Types
PaymentReceipt Event
Emitted when a payment is processed (registry or ephemeral).
type PaymentReceipt = {
payment_type: 'Registry' | 'Ephemeral'; // Payment model used
nonce: string; // Payment identifier
amount: string; // Amount (as string)
receiver: string; // Recipient address
coin_type: string; // Coin type
timestamp_ms: string; // Unix timestamp in ms
};Extracting from Transaction Result:
const result = await client.signAndExecuteTransaction({
transaction: tx,
signer: keypair,
options: {
showEvents: true,
},
});
const receiptEvent = result.events?.find((event) => event.type.includes('PaymentReceipt'));
if (receiptEvent) {
const receipt = receiptEvent.parsedJson as PaymentReceipt;
console.log('Payment Type:', receipt.payment_type);
console.log('Nonce:', receipt.nonce);
console.log('Amount:', receipt.amount);
}Error Handling
PaymentKitClientError
Custom error class for Payment Kit errors.
class PaymentKitClientError extends Error {
constructor(message: string);
}Future Versions
Check the CHANGELOG for updates.