import {z} from 'zod' export type DomainName = string; export type OperationPreviewParameter = boolean; export type OwnerType = 'NONE' | 'UD' | 'SELF' | 'EXTERNAL'; export type OwnerAddress = string; export type DomainUpdateRequestBodyOwner = {type: OwnerType, address: OwnerAddress}; export type UpdateDomainRecords = {[key: string]: string}; export type DomainUpdateRequestBody = {owner?: DomainUpdateRequestBodyOwner | undefined, records?: UpdateDomainRecords | undefined}; export type UpdateApiDomainsNameArgs = {name: DomainName, $preview?: OperationPreviewParameter | undefined, body: DomainUpdateRequestBody}; export type UpdateApiDomainsNameOptions = {baseUrl?: string | undefined, bearer?: string | undefined, fetch?: typeof fetch | undefined}; export const operationStatus = z.enum(["QUEUED", "SIGNATURE_REQUIRED", "PROCESSING", "COMPLETED", "FAILED", "CANCELLED"]); export const operationType = z.enum(["DOMAIN_CLAIM", "DOMAIN_UPDATE", "DOMAIN_RETURN", "WALLET_CREATE", "WALLET_UPDATE", "WALLET_VERIFY", "ACCOUNT_UPDATE"]); export const domainName = z.string(); export const blockchainType = z.enum(["MATIC", "ETH", "BASE"]); export const subOperationTransactionResponse = z.object({hash: z.string().optional(), blockchain: blockchainType}); export const domainRecords = z.record(z.string(), z.string()); export const ownerAddress = z.string(); export const mintParametersResponse = z.object({initialRecords: domainRecords.optional(), toAddress: ownerAddress}); export const mintSubOperationResponse = z.object({id: z.string(), status: operationStatus, "@type": z.literal("unstoppabledomains.com/partner.v3.BlockchainOperation"), transaction: subOperationTransactionResponse.optional(), type: z.literal("MINT"), parameters: mintParametersResponse}); export const updateRecordsParametersResponse = z.object({recordUpdates: domainRecords, resetRecords: z.boolean()}); export const updateRecordsSubOperationResponse = z.object({id: z.string(), status: operationStatus, "@type": z.literal("unstoppabledomains.com/partner.v3.BlockchainOperation"), transaction: subOperationTransactionResponse.optional(), type: z.literal("UPDATE_RECORDS"), parameters: updateRecordsParametersResponse}); export const transferParametersResponse = z.object({fromAddress: ownerAddress, toAddress: ownerAddress, resetRecords: z.boolean()}); export const transferSubOperationResponse = z.object({id: z.string(), status: operationStatus, "@type": z.literal("unstoppabledomains.com/partner.v3.BlockchainOperation"), transaction: subOperationTransactionResponse.optional(), type: z.literal("TRANSFER"), parameters: transferParametersResponse}); export const returnSubOperationResponse = z.object({id: z.string(), status: operationStatus, "@type": z.literal("unstoppabledomains.com/partner.v3.BlockchainOperation"), transaction: subOperationTransactionResponse.optional(), type: z.literal("RETURN")}); export const walletCreateResultResponse = z.object({address: ownerAddress}); export const walletCreateSubOperationResponse = z.object({id: z.string(), status: operationStatus, "@type": z.literal("unstoppabledomains.com/partner.v3.PlatformOperation"), result: walletCreateResultResponse.optional(), type: z.literal("WALLET_CREATE")}); export const walletSetDefaultParametersResponse = z.object({address: ownerAddress}); export const walletSetDefaultSubOperationResponse = z.object({id: z.string(), status: operationStatus, "@type": z.literal("unstoppabledomains.com/partner.v3.PlatformOperation"), parameters: walletSetDefaultParametersResponse, type: z.literal("WALLET_SET_DEFAULT")}); export const webhookType = z.enum(["OPERATION_FINISHED", "OPERATION_ACTION_REQUIRED"]); export const webhookCreateParametersResponse = z.object({type: webhookType, url: z.string()}); export const webhookCreateResultResponse = z.object({id: z.string()}); export const webhookCreateSubOperationResponse = z.object({id: z.string(), status: operationStatus, "@type": z.literal("unstoppabledomains.com/partner.v3.PlatformOperation"), parameters: webhookCreateParametersResponse, result: webhookCreateResultResponse.optional(), type: z.literal("WEBHOOK_CREATE")}); export const webhookDeleteParametersResponse = z.object({id: z.string()}); export const webhookDeleteSubOperationResponse = z.object({id: z.string(), status: operationStatus, "@type": z.literal("unstoppabledomains.com/partner.v3.PlatformOperation"), parameters: webhookDeleteParametersResponse, type: z.literal("WEBHOOK_DELETE")}); export const operationCheckResponse = z.object({id: z.string(), "@type": z.literal("unstoppabledomains.com/partner.v3.Operation"), status: operationStatus, type: operationType, domain: domainName.optional(), lastUpdatedTimestamp: z.number(), dependencies: z.array(z.union([mintSubOperationResponse, updateRecordsSubOperationResponse, transferSubOperationResponse, returnSubOperationResponse, walletCreateSubOperationResponse, walletSetDefaultSubOperationResponse, webhookCreateSubOperationResponse, webhookDeleteSubOperationResponse]))}); export const domainOperationResponse = z.object({"@type": z.literal("unstoppabledomains.com/partner.v3.DomainOperationResult"), operation: operationCheckResponse}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Update a domain (overwriting update) * * PUT /domains/{name} */ export const updateApiDomainsName = async (args: UpdateApiDomainsNameArgs, options?: UpdateApiDomainsNameOptions) => { const {baseUrl = "https://api.unstoppabledomains.com/partner/v3", fetch: fetchFn = fetch, bearer} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (args.$preview != null) query.append("$preview", String(args.$preview)) if (bearer !== undefined) headers.set('authorization', `Bearer ${bearer}`) const url = `${baseUrl.replace(/\/+$/, '')}/domains/${encodeURIComponent(String(args.name))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "PUT", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(domainOperationResponse, await res.json()) };