import {z} from 'zod' export type BlockchainTransactionType = 'send' | 'multi-withdraw' | 'account-set' | 'approve-hot-key' | 'approve-builder-fee' | 'allowance' | 'smart-call' | 'multi-smart-call' | 'activate' | 'activate-trading' | 'stake-delegation' | 'stake-nomination' | 'stake-undelegation' | 'complete-withdrawal' | 'stake-complete-deposit' | 'take-reward' | 'claim-builder-rewards' | 'pool-creation' | 'edit-pool' | 'governance-vote' | 'unjail' | 'importance-transfer' | 'transfer-stake' | 'rebond-stake' | 'chill' | 'cross-chain-send' | 'accept-deposit' | 'reject-deposit' | 'allocate' | 'reject-allocation' | 'create-allocation-request' | 'settle-allocations' | 'cancel-allocations' | 'create-referral' | 'set-referral' | 'set-trading'; export type DeliveryType = 'free-of-payment' | 'payment-vs-payment'; export type FeeLevel = 'low' | 'medium' | 'high'; export type LimitType = 'otc' | 'rfq'; export type TargetType = 'external' | 'portfolio'; export type WithdrawTarget = {cryptoAddressId?: string | undefined, portfolioId?: string | undefined, targetType: TargetType}; export type OrderType = 'sell' | 'buy' | 'deposit' | 'withdraw' | 'multi-withdraw' | 'wallet-message' | 'retrieved-deposit' | 'earn-reward' | 'earn-shared-reward' | 'claim-shared-reward' | 'cross-chain-deposit' | 'cross-chain-withdraw'; export type OrderReceiver = {amount?: string | undefined, toAddress?: string | undefined, toCryptoAddressId?: string | undefined}; export type UserAbstraction = ; export type CreateOrder = {agentAddress?: string | undefined, agentName?: string | undefined, agentValidUntil?: string | undefined, amount?: string | undefined, baseCurrency: string, blockchainTransactionType?: BlockchainTransactionType | undefined, builderFeeAddress?: string | undefined, deliveryType?: DeliveryType | undefined, description?: string | undefined, externalBroadcast?: boolean | undefined, externalOrderId: string, feeLevel?: FeeLevel | undefined, includeFeeInWithdraw?: boolean | undefined, limitType?: LimitType | undefined, mainCurrency?: string | undefined, masterPassword?: string | undefined, memo?: string | undefined, netuid?: string | undefined, nextTransferTo?: Array | undefined, optInReferralProgram?: boolean | undefined, orderType: OrderType, payload?: string | undefined, payloads?: Array | undefined, portfolioId: string, priceLimit?: string | undefined, quoteAmount?: string | undefined, quoteCurrency?: string | undefined, quoteMainCurrency?: string | undefined, referralCode?: string | undefined, toAddress?: string | undefined, toCounterpartyId?: string | undefined, toCryptoAddressId?: string | undefined, toPortfolioId?: string | undefined, toReceivers?: Array | undefined, userAbstract?: UserAbstraction | undefined}; export type CreateOrders = {orders: Array}; export type CreateApiOrdersArgs = {'Content-Type'?: string | undefined, body: CreateOrders}; export type CreateApiOrdersOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const blockchainTransactionType = z.enum(["send", "multi-withdraw", "account-set", "approve-hot-key", "approve-builder-fee", "allowance", "smart-call", "multi-smart-call", "activate", "activate-trading", "stake-delegation", "stake-nomination", "stake-undelegation", "complete-withdrawal", "stake-complete-deposit", "take-reward", "claim-builder-rewards", "pool-creation", "edit-pool", "governance-vote", "unjail", "importance-transfer", "transfer-stake", "rebond-stake", "chill", "cross-chain-send", "accept-deposit", "reject-deposit", "allocate", "reject-allocation", "create-allocation-request", "settle-allocations", "cancel-allocations", "create-referral", "set-referral", "set-trading"]); export const clearLoopExtra = z.object({clearLoopExternalNetted: z.boolean().optional(), clearLoopSettlementId: z.string().optional()}); export const deliveryType = z.enum(["free-of-payment", "payment-vs-payment"]); export const depositOrigin = z.enum([]); export const minimalUnit = z.object({}); export const feeType = z.enum([]); export const feeEstimation = z.object({baseFeePerGas: z.string().optional(), estimatedTime: z.string().optional(), fee: z.string(), feeCurrency: z.string(), feePerByte: minimalUnit.optional(), feeType: feeType.optional(), gasLimit: minimalUnit.optional(), gasPriceGwei: z.string().optional(), maxFeePerGas: z.string().optional(), maxPriorityFeePerGas: z.string().optional(), reportingCurrencyRate: z.string().optional(), transactionBytes: z.string().optional()}); export const feeLevel = z.enum(["low", "medium", "high"]); export const currencyConfigurationExtra = z.object({}); export const currencyConfiguration = z.object({createdAt: z.string(), createdBy: z.string(), cryptoAddressId: z.string(), currency: z.string(), currencyConfigurationId: z.string(), extra: currencyConfigurationExtra.optional(), isWhitelist: z.boolean(), lastUsedAt: z.string().optional(), portfolioIds: z.array(z.string()).optional(), updatedAt: z.string().optional(), updatedBy: z.string().optional()}); export const cryptoAddressEmbedded = z.object({currencyConfigurations: z.array(currencyConfiguration).optional()}); export const addressTag = z.enum([]); export const addressType = z.enum(["externally-owned-account", "internal-account", "smart-contract", "payable-smart-contract"]); export const addressCategory = z.enum(["smart-contract", "payable-smart-contract", "mining", "unknown", "self-hosted", "vasp"]); export const cryptoAddressExtra = z.object({}); export const cryptoAddress = z.object({_embedded: cryptoAddressEmbedded.optional(), acceptTokens: z.boolean().optional(), address: z.string(), addressTags: z.array(addressTag).optional(), addressType: addressType, category: addressCategory.optional(), createdAt: z.string(), createdBy: z.string(), cryptoAddressId: z.string(), currency: z.string(), extra: cryptoAddressExtra.optional(), isWhitelist: z.boolean(), lastUsedAt: z.string().optional(), mainCurrency: z.string().optional(), memo: z.string().optional(), name: z.string(), organizationId: z.string().optional(), portfolioIds: z.array(z.string()).optional(), updatedAt: z.string().optional(), updatedBy: z.string().optional()}); export const targetType = z.enum(["external", "portfolio"]); export const withdrawTarget = z.object({cryptoAddressId: z.string().optional(), portfolioId: z.string().optional(), targetType: targetType}); export const uploadPartSignedTx = z.object({}); export const uploadFullSignedTx = z.object({}); export const orderExtra = z.object({availableCoSigners: z.array(z.string()).optional(), availableSnapshot: z.string().optional(), balanceSnapshot: z.string().optional(), blockchainTransactionType: blockchainTransactionType.optional(), clearLoop: z.boolean().optional(), clearLoopExtra: clearLoopExtra.optional(), clientAccountId: z.string().optional(), coSigners: z.array(z.string()).optional(), coSignersNumber: z.string().optional(), confirmations: z.string().optional(), counterpartyPortfolioId: z.string().optional(), deliveryType: deliveryType.optional(), depositOrderId: z.string().optional(), depositOrigin: depositOrigin.optional(), depositTargetId: z.string().optional(), description: z.string().optional(), estimatedFees: feeEstimation.optional(), externalBroadcast: z.boolean().optional(), feeLevel: feeLevel.optional(), fees: z.array(feeEstimation).optional(), fromAddresses: z.array(z.string()).optional(), fromCounterpartyId: z.string().optional(), fromCryptoAddress: cryptoAddress.optional(), fromCryptoAddressId: z.string().optional(), fromPortfolioId: z.string().optional(), includeFeeInWithdraw: z.boolean().optional(), invoiceId: z.string().optional(), marketPrice: z.string().optional(), memo: z.string().optional(), nextTransferTo: z.array(withdrawTarget).optional(), originalDepositAmount: z.string().optional(), partSigned: uploadPartSignedTx.optional(), payload: z.string().optional(), payloads: z.array(z.string()).optional(), reportingCurrencyRate: z.string().optional(), reportingQuoteCurrencyRate: z.string().optional(), signed: uploadFullSignedTx.optional(), spenderAddress: z.string().optional(), terminatedReportingCurrencyRate: z.string().optional(), toAddress: z.string().optional(), toCounterpartyId: z.string().optional(), toCryptoAddressId: z.string().optional(), toInvoiceId: z.string().optional(), toLendingInvoiceId: z.string().optional(), toPortfolioId: z.string().optional(), totalQuoteAmount: z.string().optional(), transactionId: z.string().optional(), transactionRequest: z.object({}).optional(), transferAmount: z.string().optional(), transferChainId: z.string().optional(), transferDepositTargetId: z.string().optional(), transferFees: z.string().optional(), transferFeesCurrency: z.string().optional(), transferTransactionId: z.string().optional(), withdrawFee: z.string().optional(), withdrawOrderId: z.string().optional()}); export const limitType = z.enum(["otc", "rfq"]); export const orderType = z.enum(["sell", "buy", "deposit", "withdraw", "multi-withdraw", "wallet-message", "retrieved-deposit", "earn-reward", "earn-shared-reward", "claim-shared-reward", "cross-chain-deposit", "cross-chain-withdraw"]); export const portfolioType = z.enum(["custody", "trading-vault", "trading", "external", "clearloop"]); export const orderStatus = z.enum(["new", "waiting-funds", "reserving", "reserved", "queued", "validating-funds", "working", "waiting-approve", "co-sign-require", "approved", "processing", "executed", "canceled", "rejecting", "rejected", "declining", "declined", "suspending", "suspended", "blocked", "action-required", "accepting", "accepted", "require-initializer-approve", "waiting-counterparty-approve", "require-counterparty-approve", "ready-for-settlement", "settled", "part-signed-tx-added", "full-signed-tx-added", "rejected-part-signed-tx-added", "rejected-full-signed-tx-added", "accepted-part-signed-tx-added", "accepted-full-signed-tx-added", "awaiting-settlement", "master-password-required", "manual-resolving", "error", "pending-atomic-settlement-confirmation", "atomic-settlement-reservation-completed", "require-finalize", "waiting-accept-deposit", "waiting-reject-deposit"]); export const order = z.object({amount: z.string(), baseCurrency: z.string(), createdAt: z.string(), createdBy: z.string().optional(), externalOrderId: z.string(), extra: orderExtra.optional(), limitType: limitType.optional(), mainCurrency: z.string().optional(), orderId: z.string(), orderType: orderType, organizationId: z.string().optional(), portfolioId: z.string(), portfolioType: portfolioType, quoteCurrency: z.string().optional(), quoteMainCurrency: z.string().optional(), status: orderStatus, terminatedAt: z.string().optional(), updatedAt: z.string().optional()}); export const orders = z.object({orders: z.array(order)}); 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 }; /** * Create Multiple Orders * * POST /orders/ */ export const createApiOrders = async (args: CreateApiOrdersArgs, options?: CreateApiOrdersOptions) => { const {baseUrl = "https://api.copper.co/platform", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/vnd.create-orders+json") headers.set('accept', "application/vnd.create-orders+json") if (args['Content-Type'] != null) headers.set("Content-Type", String(args['Content-Type'])) const url = `${baseUrl.replace(/\/+$/, '')}/orders/${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", 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(orders, await res.json()) };