import {z} from 'zod' 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 OrderStatus = '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 type PortfolioType = 'custody' | 'trading-vault' | 'trading' | 'external' | 'clearloop'; export type GetApiOrdersArgs = {portfolioIds?: Array | undefined, currencies?: Array | undefined, baseCurrencies?: Array | undefined, quoteCurrencies?: Array | undefined, mainCurrencies?: Array | undefined, orderTypes?: Array | undefined, statuses?: Array | undefined, offset?: string | undefined, limit?: string | undefined, externalOrderId?: string | undefined, transferChainId?: string | undefined, transactionId?: string | undefined, searchQuery?: string | undefined, updatedSince?: string | undefined, createdSince?: string | undefined, createdAtFrom?: string | undefined, createdAtTo?: string | undefined, terminatedAtFrom?: string | undefined, terminatedAtTo?: string | undefined, portfolioTypes?: Array | undefined, excludedPortfolioTypes?: Array | undefined, counterpartyId?: string | undefined}; export type GetApiOrdersOptions = {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 }; /** * Get Orders * * GET /orders */ export const getApiOrders = async (args: GetApiOrdersArgs, options?: GetApiOrdersOptions) => { const {baseUrl = "https://api.copper.co/platform", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") for (const item of args.portfolioIds ?? []) query.append("portfolioIds", String(item)) for (const item of args.currencies ?? []) query.append("currencies", String(item)) for (const item of args.baseCurrencies ?? []) query.append("baseCurrencies", String(item)) for (const item of args.quoteCurrencies ?? []) query.append("quoteCurrencies", String(item)) for (const item of args.mainCurrencies ?? []) query.append("mainCurrencies", String(item)) for (const item of args.orderTypes ?? []) query.append("orderTypes", String(item)) for (const item of args.statuses ?? []) query.append("statuses", String(item)) if (args.offset != null) query.append("offset", String(args.offset)) if (args.limit != null) query.append("limit", String(args.limit)) if (args.externalOrderId != null) query.append("externalOrderId", String(args.externalOrderId)) if (args.transferChainId != null) query.append("transferChainId", String(args.transferChainId)) if (args.transactionId != null) query.append("transactionId", String(args.transactionId)) if (args.searchQuery != null) query.append("searchQuery", String(args.searchQuery)) if (args.updatedSince != null) query.append("updatedSince", String(args.updatedSince)) if (args.createdSince != null) query.append("createdSince", String(args.createdSince)) if (args.createdAtFrom != null) query.append("createdAtFrom", String(args.createdAtFrom)) if (args.createdAtTo != null) query.append("createdAtTo", String(args.createdAtTo)) if (args.terminatedAtFrom != null) query.append("terminatedAtFrom", String(args.terminatedAtFrom)) if (args.terminatedAtTo != null) query.append("terminatedAtTo", String(args.terminatedAtTo)) for (const item of args.portfolioTypes ?? []) query.append("portfolioTypes", String(item)) for (const item of args.excludedPortfolioTypes ?? []) query.append("excludedPortfolioTypes", String(item)) if (args.counterpartyId != null) query.append("counterpartyId", String(args.counterpartyId)) const url = `${baseUrl.replace(/\/+$/, '')}/orders${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) 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()) };