@coin-voyage/paykit-headless
v0.0.2
Published
Headless CoinVoyage PayKit clients and protocol helpers.
Maintainers
Readme
@coin-voyage/paykit-headless
Headless helpers for CoinVoyage PayKit and x402 payments in agent or server runtimes.
What This Package Does
@coin-voyage/paykit-headless is intended for agents and backend services that need to pay
CoinVoyage x402 PAYMENT-REQUIRED challenges without a browser wallet UI.
For EVM and Solana payments, it wraps the default x402 EVM and SVM clients and provides a single
agent-oriented helper for fetching a challenge, signing the selected accepts[] entry, and retrying
the protected resource.
For Sui payments, it adds CoinVoyage-specific support that generic x402 clients do not provide yet:
it can select a sui:mainnet accept, build or sign the required Sui transaction payload, and return a
valid PAYMENT-SIGNATURE header for CoinVoyage's verifier.
Installation
npm install @coin-voyage/paykit-headlessExports
The package exposes two public entry points:
import { readResponseBody } from "@coin-voyage/paykit-headless"
import {
executeX402AgentPayment,
createSuiX402PaymentSignatureHeader,
decodeX402PaymentRequiredHeader,
type X402AgentPaymentRequest,
} from "@coin-voyage/paykit-headless/x402"Do not import internal files such as x402/agent or x402/sui; use the x402 barrel.
Agent Payment Flow
Use executeX402AgentPayment when the agent should fetch a PAYMENT-REQUIRED challenge, create a
PAYMENT-SIGNATURE, and retry the protected resource.
import { executeX402AgentPayment } from "@coin-voyage/paykit-headless/x402"
const coinType = "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC"
const privateKey = process.env.AGENT_SUI_PRIVATE_KEY
const url = new URL("https://example.com/api/agent/payment-required")
url.searchParams.set("preferred_chain_type", "SUI")
url.searchParams.set("preferred_chain_id", "30000000000002")
url.searchParams.set("preferred_token_address", coinType)
const result = await executeX402AgentPayment({
url: url.toString(),
chainType: "SUI",
network: "sui:mainnet",
asset: coinType,
maxAmount: "20000",
privateKey,
})
if (!result.ok) {
throw new Error(result.message)
}privateKey must match chainType:
| chainType | Expected key |
| --- | --- |
| EVM | EVM private key for eip155:* accepts |
| SOL | Solana private key for solana:* accepts |
| SUI | Sui Ed25519 private key for sui:* accepts |
The agent filters accepts[] by chainType, then by network, asset, paymentIdentifier, and
maxAmount when those fields are provided.
Payment Requirement Preferences
X402RequirementRequest is optional as a whole. If you send it, include both
preferred_chain_type and preferred_token_address.
Valid tailored request:
{
"preferred_chain_type": "SUI",
"preferred_chain_id": 30000000000002,
"preferred_token_address": "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC"
}Do not request only ?preferred_chain_type=SUI. If you do not need a tailored token response, omit all
preference fields and choose from the returned accepts[].
Existing PAYMENT-REQUIRED Header
If you already fetched a challenge, pass the header to executeX402AgentPayment:
const result = await executeX402AgentPayment({
url: "https://example.com/api/agent/payment-required",
paymentRequiredHeader,
chainType: "SUI",
network: "sui:mainnet",
asset: coinType,
maxAmount: "20000",
privateKey,
})For Sui-only integrations that only need the signature header:
import { createSuiX402PaymentSignatureHeader } from "@coin-voyage/paykit-headless/x402"
const { paymentSignature } = await createSuiX402PaymentSignatureHeader(paymentRequiredHeader, {
network: "sui:mainnet",
asset: coinType,
maxAmount: "20000",
privateKey,
rpcUrl: process.env.SUI_RPC_URL,
})Sui PAYMENT-SIGNATURE Payload
Sui x402 support uses a CoinVoyage-specific payload carried in the standard base64
PAYMENT-SIGNATURE header. The SDK:
- Selects the returned
sui:mainnetaccepts[]entry without changingscheme,network,asset,amount,payTo, orpaymentIdentifier. - Builds a Sui programmable transaction block when the backend does not provide transaction bytes.
- Transfers the exact raw
amountof the exact Sui coin type topayTo. - Signs the transaction with the configured Sui Ed25519 key.
- Encodes the signed transaction bytes, signature, payer address, selected accept, and CoinVoyage Sui
payload fields into
PAYMENT-SIGNATURE.
If the server provides prepared Sui transaction bytes in accept.transactionBytes, accept.txBytes,
accept.extra.sui.transactionBytes, or accept.extra.sui.txBytes, the SDK signs those bytes instead
of constructing a transfer transaction. It is valid for the backend extra object to contain only
paymentIdentifier; in that case the SDK builds the Sui PTB from the payer's owned coins.
Current Limits
- Native ETH and native SOL accepts are not supported by the headless agent. Use token accepts such as USDC.
- Sui accepts require this SDK or another client that implements CoinVoyage's Sui
PAYMENT-SIGNATUREpayload. - The
maxAmountvalue is compared against the raw token amount, not display units.
Key Handling
The package does not read private keys or RPC URLs from environment variables. Your application is
responsible for loading the correct key and passing it as privateKey.
For each payment attempt, pass the key that matches chainType. For example, pass a Sui Ed25519 key
when chainType is "SUI", an EVM private key when chainType is "EVM", and a Solana private key
when chainType is "SOL".
